summaryrefslogtreecommitdiff
path: root/src/hid_core
diff options
context:
space:
mode:
authorGravatar german772024-01-07 09:05:12 -0600
committerGravatar Narr the Reg2024-01-11 19:35:04 -0600
commitb5dac5f525e8d5884506ebd98a530e237b518480 (patch)
tree6ceee925ba897dc3450bdad209982f0be4bc3f7a /src/hid_core
parentMerge pull request #12653 from liamwhite/once-more (diff)
downloadyuzu-b5dac5f525e8d5884506ebd98a530e237b518480.tar.gz
yuzu-b5dac5f525e8d5884506ebd98a530e237b518480.tar.xz
yuzu-b5dac5f525e8d5884506ebd98a530e237b518480.zip
service: hid: Create abstracted pad structure
Diffstat (limited to 'src/hid_core')
-rw-r--r--src/hid_core/CMakeLists.txt34
-rw-r--r--src/hid_core/frontend/emulated_controller.cpp22
-rw-r--r--src/hid_core/hid_types.h3
-rw-r--r--src/hid_core/hid_util.h2
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp197
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_battery_handler.h49
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp199
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_button_handler.h75
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp126
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h56
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp123
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_led_handler.h43
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp108
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h52
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp140
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h57
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_pad.cpp294
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_pad.h123
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp99
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_pad_holder.h47
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp47
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_palma_handler.h37
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp322
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_properties_handler.h86
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp154
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h61
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp73
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h51
-rw-r--r--src/hid_core/resources/npad/npad.cpp8
-rw-r--r--src/hid_core/resources/npad/npad_data.cpp2
-rw-r--r--src/hid_core/resources/npad/npad_types.h99
-rw-r--r--src/hid_core/resources/npad/npad_vibration.cpp80
-rw-r--r--src/hid_core/resources/npad/npad_vibration.h34
-rw-r--r--src/hid_core/resources/six_axis/six_axis.cpp6
-rw-r--r--src/hid_core/resources/vibration/gc_vibration_device.cpp106
-rw-r--r--src/hid_core/resources/vibration/gc_vibration_device.h31
-rw-r--r--src/hid_core/resources/vibration/n64_vibration_device.cpp80
-rw-r--r--src/hid_core/resources/vibration/n64_vibration_device.h29
-rw-r--r--src/hid_core/resources/vibration/vibration_base.cpp30
-rw-r--r--src/hid_core/resources/vibration/vibration_base.h28
-rw-r--r--src/hid_core/resources/vibration/vibration_device.cpp84
-rw-r--r--src/hid_core/resources/vibration/vibration_device.h35
42 files changed, 3311 insertions, 21 deletions
diff --git a/src/hid_core/CMakeLists.txt b/src/hid_core/CMakeLists.txt
index cce4e6857..aa85502b5 100644
--- a/src/hid_core/CMakeLists.txt
+++ b/src/hid_core/CMakeLists.txt
@@ -36,6 +36,30 @@ add_library(hid_core STATIC
36 irsensor/processor_base.h 36 irsensor/processor_base.h
37 irsensor/tera_plugin_processor.cpp 37 irsensor/tera_plugin_processor.cpp
38 irsensor/tera_plugin_processor.h 38 irsensor/tera_plugin_processor.h
39 resources/abstracted_pad/abstract_battery_handler.cpp
40 resources/abstracted_pad/abstract_battery_handler.h
41 resources/abstracted_pad/abstract_button_handler.cpp
42 resources/abstracted_pad/abstract_button_handler.h
43 resources/abstracted_pad/abstract_ir_sensor_handler.cpp
44 resources/abstracted_pad/abstract_ir_sensor_handler.h
45 resources/abstracted_pad/abstract_led_handler.cpp
46 resources/abstracted_pad/abstract_led_handler.h
47 resources/abstracted_pad/abstract_mcu_handler.cpp
48 resources/abstracted_pad/abstract_mcu_handler.h
49 resources/abstracted_pad/abstract_nfc_handler.cpp
50 resources/abstracted_pad/abstract_nfc_handler.h
51 resources/abstracted_pad/abstract_pad.cpp
52 resources/abstracted_pad/abstract_pad.h
53 resources/abstracted_pad/abstract_pad_holder.cpp
54 resources/abstracted_pad/abstract_pad_holder.h
55 resources/abstracted_pad/abstract_palma_handler.cpp
56 resources/abstracted_pad/abstract_palma_handler.h
57 resources/abstracted_pad/abstract_properties_handler.cpp
58 resources/abstracted_pad/abstract_properties_handler.h
59 resources/abstracted_pad/abstract_sixaxis_handler.cpp
60 resources/abstracted_pad/abstract_sixaxis_handler.h
61 resources/abstracted_pad/abstract_vibration_handler.cpp
62 resources/abstracted_pad/abstract_vibration_handler.h
39 resources/debug_pad/debug_pad.cpp 63 resources/debug_pad/debug_pad.cpp
40 resources/debug_pad/debug_pad.h 64 resources/debug_pad/debug_pad.h
41 resources/debug_pad/debug_pad_types.h 65 resources/debug_pad/debug_pad_types.h
@@ -56,6 +80,8 @@ add_library(hid_core STATIC
56 resources/npad/npad_resource.cpp 80 resources/npad/npad_resource.cpp
57 resources/npad/npad_resource.h 81 resources/npad/npad_resource.h
58 resources/npad/npad_types.h 82 resources/npad/npad_types.h
83 resources/npad/npad_vibration.cpp
84 resources/npad/npad_vibration.h
59 resources/palma/palma.cpp 85 resources/palma/palma.cpp
60 resources/palma/palma.h 86 resources/palma/palma.h
61 resources/six_axis/console_six_axis.cpp 87 resources/six_axis/console_six_axis.cpp
@@ -78,6 +104,14 @@ add_library(hid_core STATIC
78 resources/touch_screen/touch_types.h 104 resources/touch_screen/touch_types.h
79 resources/unique_pad/unique_pad.cpp 105 resources/unique_pad/unique_pad.cpp
80 resources/unique_pad/unique_pad.h 106 resources/unique_pad/unique_pad.h
107 resources/vibration/gc_vibration_device.h
108 resources/vibration/gc_vibration_device.cpp
109 resources/vibration/n64_vibration_device.h
110 resources/vibration/n64_vibration_device.cpp
111 resources/vibration/vibration_base.h
112 resources/vibration/vibration_base.cpp
113 resources/vibration/vibration_device.h
114 resources/vibration/vibration_device.cpp
81 resources/applet_resource.cpp 115 resources/applet_resource.cpp
82 resources/applet_resource.h 116 resources/applet_resource.h
83 resources/controller_base.cpp 117 resources/controller_base.cpp
diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp
index 3d2d1e9f9..a6a96935d 100644
--- a/src/hid_core/frontend/emulated_controller.cpp
+++ b/src/hid_core/frontend/emulated_controller.cpp
@@ -27,7 +27,7 @@ EmulatedController::~EmulatedController() = default;
27NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { 27NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) {
28 switch (type) { 28 switch (type) {
29 case Settings::ControllerType::ProController: 29 case Settings::ControllerType::ProController:
30 return NpadStyleIndex::ProController; 30 return NpadStyleIndex::Fullkey;
31 case Settings::ControllerType::DualJoyconDetached: 31 case Settings::ControllerType::DualJoyconDetached:
32 return NpadStyleIndex::JoyconDual; 32 return NpadStyleIndex::JoyconDual;
33 case Settings::ControllerType::LeftJoycon: 33 case Settings::ControllerType::LeftJoycon:
@@ -49,13 +49,13 @@ NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerTyp
49 case Settings::ControllerType::SegaGenesis: 49 case Settings::ControllerType::SegaGenesis:
50 return NpadStyleIndex::SegaGenesis; 50 return NpadStyleIndex::SegaGenesis;
51 default: 51 default:
52 return NpadStyleIndex::ProController; 52 return NpadStyleIndex::Fullkey;
53 } 53 }
54} 54}
55 55
56Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { 56Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) {
57 switch (type) { 57 switch (type) {
58 case NpadStyleIndex::ProController: 58 case NpadStyleIndex::Fullkey:
59 return Settings::ControllerType::ProController; 59 return Settings::ControllerType::ProController;
60 case NpadStyleIndex::JoyconDual: 60 case NpadStyleIndex::JoyconDual:
61 return Settings::ControllerType::DualJoyconDetached; 61 return Settings::ControllerType::DualJoyconDetached;
@@ -106,7 +106,7 @@ void EmulatedController::ReloadFromSettings() {
106 SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); 106 SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
107 original_npad_type = npad_type; 107 original_npad_type = npad_type;
108 } else { 108 } else {
109 SetNpadStyleIndex(NpadStyleIndex::ProController); 109 SetNpadStyleIndex(NpadStyleIndex::Fullkey);
110 original_npad_type = npad_type; 110 original_npad_type = npad_type;
111 } 111 }
112 112
@@ -1073,7 +1073,7 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
1073 .body = GetNpadColor(controller.color_values[index].body), 1073 .body = GetNpadColor(controller.color_values[index].body),
1074 .button = GetNpadColor(controller.color_values[index].buttons), 1074 .button = GetNpadColor(controller.color_values[index].buttons),
1075 }; 1075 };
1076 if (npad_type == NpadStyleIndex::ProController) { 1076 if (npad_type == NpadStyleIndex::Fullkey) {
1077 controller.colors_state.left = { 1077 controller.colors_state.left = {
1078 .body = GetNpadColor(controller.color_values[index].left_grip), 1078 .body = GetNpadColor(controller.color_values[index].left_grip),
1079 .button = GetNpadColor(controller.color_values[index].buttons), 1079 .button = GetNpadColor(controller.color_values[index].buttons),
@@ -1356,7 +1356,7 @@ bool EmulatedController::HasNfc() const {
1356 switch (npad_type) { 1356 switch (npad_type) {
1357 case NpadStyleIndex::JoyconRight: 1357 case NpadStyleIndex::JoyconRight:
1358 case NpadStyleIndex::JoyconDual: 1358 case NpadStyleIndex::JoyconDual:
1359 case NpadStyleIndex::ProController: 1359 case NpadStyleIndex::Fullkey:
1360 case NpadStyleIndex::Handheld: 1360 case NpadStyleIndex::Handheld:
1361 break; 1361 break;
1362 default: 1362 default:
@@ -1548,7 +1548,7 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
1548 // Fallback Fullkey controllers to Pro controllers 1548 // Fallback Fullkey controllers to Pro controllers
1549 if (IsControllerFullkey() && supported_style_tag.fullkey) { 1549 if (IsControllerFullkey() && supported_style_tag.fullkey) {
1550 LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); 1550 LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
1551 SetNpadStyleIndex(NpadStyleIndex::ProController); 1551 SetNpadStyleIndex(NpadStyleIndex::Fullkey);
1552 Connect(); 1552 Connect();
1553 return; 1553 return;
1554 } 1554 }
@@ -1556,13 +1556,13 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
1556 // Fallback Dual joycon controllers to Pro controllers 1556 // Fallback Dual joycon controllers to Pro controllers
1557 if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { 1557 if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) {
1558 LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); 1558 LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
1559 SetNpadStyleIndex(NpadStyleIndex::ProController); 1559 SetNpadStyleIndex(NpadStyleIndex::Fullkey);
1560 Connect(); 1560 Connect();
1561 return; 1561 return;
1562 } 1562 }
1563 1563
1564 // Fallback Pro controllers to Dual joycon 1564 // Fallback Pro controllers to Dual joycon
1565 if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) { 1565 if (npad_type == NpadStyleIndex::Fullkey && supported_style_tag.joycon_dual) {
1566 LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); 1566 LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type);
1567 SetNpadStyleIndex(NpadStyleIndex::JoyconDual); 1567 SetNpadStyleIndex(NpadStyleIndex::JoyconDual);
1568 Connect(); 1568 Connect();
@@ -1577,7 +1577,7 @@ bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const {
1577 std::scoped_lock lock{mutex}; 1577 std::scoped_lock lock{mutex};
1578 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; 1578 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
1579 switch (type) { 1579 switch (type) {
1580 case NpadStyleIndex::ProController: 1580 case NpadStyleIndex::Fullkey:
1581 case NpadStyleIndex::GameCube: 1581 case NpadStyleIndex::GameCube:
1582 case NpadStyleIndex::NES: 1582 case NpadStyleIndex::NES:
1583 case NpadStyleIndex::SNES: 1583 case NpadStyleIndex::SNES:
@@ -1593,7 +1593,7 @@ bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
1593 std::scoped_lock lock{mutex}; 1593 std::scoped_lock lock{mutex};
1594 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; 1594 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
1595 switch (type) { 1595 switch (type) {
1596 case NpadStyleIndex::ProController: 1596 case NpadStyleIndex::Fullkey:
1597 return supported_style_tag.fullkey.As<bool>(); 1597 return supported_style_tag.fullkey.As<bool>();
1598 case NpadStyleIndex::Handheld: 1598 case NpadStyleIndex::Handheld:
1599 return supported_style_tag.handheld.As<bool>(); 1599 return supported_style_tag.handheld.As<bool>();
diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h
index a81ed6af0..2c3f02f34 100644
--- a/src/hid_core/hid_types.h
+++ b/src/hid_core/hid_types.h
@@ -220,6 +220,7 @@ enum class NpadIdType : u32 {
220}; 220};
221 221
222enum class NpadInterfaceType : u8 { 222enum class NpadInterfaceType : u8 {
223 None = 0,
223 Bluetooth = 1, 224 Bluetooth = 1,
224 Rail = 2, 225 Rail = 2,
225 Usb = 3, 226 Usb = 3,
@@ -229,7 +230,7 @@ enum class NpadInterfaceType : u8 {
229// This is nn::hid::NpadStyleIndex 230// This is nn::hid::NpadStyleIndex
230enum class NpadStyleIndex : u8 { 231enum class NpadStyleIndex : u8 {
231 None = 0, 232 None = 0,
232 ProController = 3, 233 Fullkey = 3,
233 Handheld = 4, 234 Handheld = 4,
234 HandheldNES = 4, 235 HandheldNES = 4,
235 JoyconDual = 5, 236 JoyconDual = 5,
diff --git a/src/hid_core/hid_util.h b/src/hid_core/hid_util.h
index 94ff2d23a..397a87472 100644
--- a/src/hid_core/hid_util.h
+++ b/src/hid_core/hid_util.h
@@ -42,7 +42,7 @@ constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& hand
42 42
43constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { 43constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) {
44 switch (handle.npad_type) { 44 switch (handle.npad_type) {
45 case Core::HID::NpadStyleIndex::ProController: 45 case Core::HID::NpadStyleIndex::Fullkey:
46 case Core::HID::NpadStyleIndex::Handheld: 46 case Core::HID::NpadStyleIndex::Handheld:
47 case Core::HID::NpadStyleIndex::JoyconDual: 47 case Core::HID::NpadStyleIndex::JoyconDual:
48 case Core::HID::NpadStyleIndex::JoyconLeft: 48 case Core::HID::NpadStyleIndex::JoyconLeft:
diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp
new file mode 100644
index 000000000..62fbbb0a7
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp
@@ -0,0 +1,197 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/core_timing.h"
5#include "hid_core/hid_result.h"
6#include "hid_core/hid_util.h"
7#include "hid_core/resources/abstracted_pad/abstract_battery_handler.h"
8#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
9#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
10#include "hid_core/resources/applet_resource.h"
11#include "hid_core/resources/npad/npad_types.h"
12#include "hid_core/resources/shared_memory_format.h"
13
14namespace Service::HID {
15
16NpadAbstractBatteryHandler::NpadAbstractBatteryHandler() {}
17
18NpadAbstractBatteryHandler::~NpadAbstractBatteryHandler() = default;
19
20void NpadAbstractBatteryHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
21 abstract_pad_holder = holder;
22}
23
24void NpadAbstractBatteryHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
25 applet_resource_holder = applet_resource;
26}
27
28void NpadAbstractBatteryHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
29 properties_handler = handler;
30}
31
32Result NpadAbstractBatteryHandler::IncrementRefCounter() {
33 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
34 return ResultNpadHandlerOverflow;
35 }
36 ref_counter++;
37 return ResultSuccess;
38}
39
40Result NpadAbstractBatteryHandler::DecrementRefCounter() {
41 if (ref_counter == 0) {
42 return ResultNpadHandlerNotInitialized;
43 }
44 ref_counter--;
45 return ResultSuccess;
46}
47
48Result NpadAbstractBatteryHandler::UpdateBatteryState(u64 aruid) {
49 const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId());
50 AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid);
51 if (aruid_data == nullptr) {
52 return ResultSuccess;
53 }
54
55 auto& npad_internal_state =
56 aruid_data->shared_memory_format->npad.npad_entry[npad_index].internal_state;
57 auto& system_properties = npad_internal_state.system_properties;
58
59 system_properties.is_charging_joy_dual.Assign(dual_battery.is_charging);
60 system_properties.is_powered_joy_dual.Assign(dual_battery.is_powered);
61 system_properties.is_charging_joy_left.Assign(left_battery.is_charging);
62 system_properties.is_powered_joy_left.Assign(left_battery.is_powered);
63 system_properties.is_charging_joy_right.Assign(right_battery.is_charging);
64 system_properties.is_powered_joy_right.Assign(right_battery.is_powered);
65
66 npad_internal_state.battery_level_dual = dual_battery.battery_level;
67 npad_internal_state.battery_level_left = left_battery.battery_level;
68 npad_internal_state.battery_level_right = right_battery.battery_level;
69
70 return ResultSuccess;
71}
72
73void NpadAbstractBatteryHandler::UpdateBatteryState() {
74 if (ref_counter == 0) {
75 return;
76 }
77 has_new_battery_data = GetNewBatteryState();
78}
79
80bool NpadAbstractBatteryHandler::GetNewBatteryState() {
81 bool has_changed = false;
82 Core::HID::NpadPowerInfo new_dual_battery_state{};
83 Core::HID::NpadPowerInfo new_left_battery_state{};
84 Core::HID::NpadPowerInfo new_right_battery_state{};
85 std::array<IAbstractedPad*, 5> abstract_pads{};
86 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
87
88 for (std::size_t i = 0; i < count; i++) {
89 auto* abstract_pad = abstract_pads[i];
90 if (!abstract_pad->internal_flags.is_connected) {
91 continue;
92 }
93 const auto power_info = abstract_pad->power_info;
94 if (power_info.battery_level > Core::HID::NpadBatteryLevel::Full) {
95 // Abort
96 continue;
97 }
98
99 const auto style = abstract_pad->assignment_style;
100
101 if (style.is_external_assigned || style.is_handheld_assigned) {
102 new_dual_battery_state = power_info;
103 }
104 if (style.is_external_left_assigned || style.is_handheld_left_assigned) {
105 new_left_battery_state = power_info;
106 }
107 if (style.is_external_right_assigned || style.is_handheld_right_assigned) {
108 new_right_battery_state = power_info;
109 }
110
111 if (abstract_pad->internal_flags.is_battery_low_ovln_required) {
112 if (abstract_pad->interface_type == Core::HID::NpadInterfaceType::Rail) {
113 // TODO
114 }
115 abstract_pad->internal_flags.is_battery_low_ovln_required.Assign(false);
116 }
117 }
118
119 if (dual_battery.battery_level != new_dual_battery_state.battery_level ||
120 dual_battery.is_charging != new_dual_battery_state.is_charging ||
121 dual_battery.is_powered != new_dual_battery_state.is_powered) {
122 has_changed = true;
123 dual_battery = new_dual_battery_state;
124 }
125
126 if (left_battery.battery_level != new_left_battery_state.battery_level ||
127 left_battery.is_charging != new_left_battery_state.is_charging ||
128 left_battery.is_powered != new_left_battery_state.is_powered) {
129 has_changed = true;
130 left_battery = new_left_battery_state;
131 }
132
133 if (right_battery.battery_level != new_right_battery_state.battery_level ||
134 right_battery.is_charging != new_right_battery_state.is_charging ||
135 right_battery.is_powered != new_right_battery_state.is_powered) {
136 has_changed = true;
137 right_battery = new_right_battery_state;
138 }
139
140 return has_changed;
141}
142
143void NpadAbstractBatteryHandler::UpdateCoreBatteryState() {
144 if (ref_counter == 0) {
145 return;
146 }
147 if (!has_new_battery_data) {
148 return;
149 }
150
151 UpdateBatteryState(0);
152}
153
154void NpadAbstractBatteryHandler::InitializeBatteryState(u64 aruid) {
155 UpdateBatteryState(aruid);
156}
157
158bool NpadAbstractBatteryHandler::HasBattery() const {
159 std::array<IAbstractedPad*, 5> abstract_pads{};
160 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
161
162 for (std::size_t i = 0; i < count; i++) {
163 const auto* abstract_pad = abstract_pads[i];
164 if (!abstract_pad->internal_flags.is_connected) {
165 continue;
166 }
167 return abstract_pad->disabled_feature_set.has_fullkey_battery ||
168 abstract_pad->disabled_feature_set.has_left_right_joy_battery;
169 }
170
171 return false;
172}
173
174void NpadAbstractBatteryHandler::HasLeftRightBattery(bool& has_left, bool& has_right) const {
175 std::array<IAbstractedPad*, 5> abstract_pads{};
176 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
177
178 has_left = false;
179 has_right = false;
180
181 for (std::size_t i = 0; i < count; i++) {
182 const auto* abstract_pad = abstract_pads[i];
183 if (!abstract_pad->internal_flags.is_connected) {
184 continue;
185 }
186 if (!abstract_pad->disabled_feature_set.has_fullkey_battery &&
187 !abstract_pad->disabled_feature_set.has_left_right_joy_battery) {
188 continue;
189 }
190 has_left = abstract_pad->assignment_style.is_external_left_assigned ||
191 abstract_pad->assignment_style.is_handheld_left_assigned;
192 has_right = abstract_pad->assignment_style.is_external_right_assigned ||
193 abstract_pad->assignment_style.is_handheld_right_assigned;
194 }
195}
196
197} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h
new file mode 100644
index 000000000..85ac5eb72
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h
@@ -0,0 +1,49 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Service::HID {
11struct AppletResourceHolder;
12class NpadAbstractedPadHolder;
13class NpadAbstractPropertiesHandler;
14
15/// Handles Npad request from HID interfaces
16class NpadAbstractBatteryHandler final {
17public:
18 explicit NpadAbstractBatteryHandler();
19 ~NpadAbstractBatteryHandler();
20
21 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
22 void SetAppletResource(AppletResourceHolder* applet_resource);
23 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
24
25 Result IncrementRefCounter();
26 Result DecrementRefCounter();
27
28 Result UpdateBatteryState(u64 aruid);
29 void UpdateBatteryState();
30 bool GetNewBatteryState();
31 void UpdateCoreBatteryState();
32 void InitializeBatteryState(u64 aruid);
33
34 bool HasBattery() const;
35 void HasLeftRightBattery(bool& has_left, bool& has_right) const;
36
37private:
38 AppletResourceHolder* applet_resource_holder{nullptr};
39 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
40 NpadAbstractPropertiesHandler* properties_handler{nullptr};
41
42 s32 ref_counter{};
43 Core::HID::NpadPowerInfo dual_battery{};
44 Core::HID::NpadPowerInfo left_battery{};
45 Core::HID::NpadPowerInfo right_battery{};
46 bool has_new_battery_data{};
47};
48
49} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp
new file mode 100644
index 000000000..587169433
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp
@@ -0,0 +1,199 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/hid_util.h"
6#include "hid_core/resources/abstracted_pad/abstract_button_handler.h"
7#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
8#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
9#include "hid_core/resources/applet_resource.h"
10#include "hid_core/resources/npad/npad_resource.h"
11#include "hid_core/resources/npad/npad_types.h"
12#include "hid_core/resources/shared_memory_format.h"
13
14namespace Service::HID {
15
16NpadAbstractButtonHandler::NpadAbstractButtonHandler() {}
17
18NpadAbstractButtonHandler::~NpadAbstractButtonHandler() = default;
19
20void NpadAbstractButtonHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
21 abstract_pad_holder = holder;
22}
23
24void NpadAbstractButtonHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
25 applet_resource_holder = applet_resource;
26}
27
28void NpadAbstractButtonHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
29 properties_handler = handler;
30}
31
32Result NpadAbstractButtonHandler::IncrementRefCounter() {
33 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
34 return ResultNpadHandlerOverflow;
35 }
36 ref_counter++;
37 return ResultSuccess;
38}
39
40Result NpadAbstractButtonHandler::DecrementRefCounter() {
41 if (ref_counter == 0) {
42 return ResultNpadHandlerNotInitialized;
43 }
44 ref_counter--;
45 return ResultSuccess;
46}
47
48Result NpadAbstractButtonHandler::UpdateAllButtonWithHomeProtection(u64 aruid) {
49 const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
50 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
51
52 if (data == nullptr) {
53 return ResultSuccess;
54 }
55
56 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
57 UpdateButtonLifo(npad_entry, aruid);
58
59 bool is_home_button_protection_enabled{};
60 const auto result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled(
61 is_home_button_protection_enabled, aruid, npad_id);
62
63 if (result.IsError()) {
64 return ResultSuccess;
65 }
66
67 npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign(
68 is_home_button_protection_enabled);
69
70 return ResultSuccess;
71}
72
73void NpadAbstractButtonHandler::UpdateAllButtonLifo() {
74 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
75 for (std::size_t i = 0; i < AruidIndexMax; i++) {
76 auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
77 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
78 UpdateButtonLifo(npad_entry, data->aruid);
79 }
80}
81
82void NpadAbstractButtonHandler::UpdateCoreBatteryState() {
83 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
84 for (std::size_t i = 0; i < AruidIndexMax; i++) {
85 auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
86 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
87 UpdateButtonLifo(npad_entry, data->aruid);
88 }
89}
90
91void NpadAbstractButtonHandler::UpdateButtonState(u64 aruid) {
92 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
93 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
94 if (data == nullptr) {
95 return;
96 }
97 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
98 UpdateButtonLifo(npad_entry, aruid);
99}
100
101Result NpadAbstractButtonHandler::SetHomeProtection(bool is_enabled, u64 aruid) {
102 const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
103 auto result = applet_resource_holder->shared_npad_resource->SetHomeProtectionEnabled(
104 aruid, npad_id, is_enabled);
105 if (result.IsError()) {
106 return result;
107 }
108
109 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
110 if (data == nullptr) {
111 return ResultSuccess;
112 }
113
114 bool is_home_protection_enabled{};
115 result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled(
116 is_home_protection_enabled, aruid, npad_id);
117 if (result.IsError()) {
118 return ResultSuccess;
119 }
120
121 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
122 npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign(
123 is_home_protection_enabled);
124 return ResultSuccess;
125}
126
127bool NpadAbstractButtonHandler::IsButtonPressedOnConsoleMode() {
128 return is_button_pressed_on_console_mode;
129}
130
131void NpadAbstractButtonHandler::EnableCenterClamp() {
132 std::array<IAbstractedPad*, 5> abstract_pads{};
133 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
134
135 for (std::size_t i = 0; i < count; i++) {
136 auto* abstract_pad = abstract_pads[i];
137 if (!abstract_pad->internal_flags.is_connected) {
138 continue;
139 }
140 abstract_pad->internal_flags.use_center_clamp.Assign(true);
141 }
142}
143
144void NpadAbstractButtonHandler::UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid) {
145 auto* npad_resource = applet_resource_holder->shared_npad_resource;
146 Core::HID::NpadStyleTag style_tag = {properties_handler->GetStyleSet(aruid)};
147 style_tag.system_ext.Assign(npad_resource->GetActiveData()->GetNpadSystemExtState());
148
149 UpdateNpadFullkeyLifo(style_tag, 0, aruid, shared_memory);
150 UpdateHandheldLifo(style_tag, 1, aruid, shared_memory);
151 UpdateJoyconDualLifo(style_tag, 2, aruid, shared_memory);
152 UpdateJoyconLeftLifo(style_tag, 3, aruid, shared_memory);
153 UpdateJoyconRightLifo(style_tag, 4, aruid, shared_memory);
154 UpdatePalmaLifo(style_tag, 5, aruid, shared_memory);
155 UpdateSystemExtLifo(style_tag, 6, aruid, shared_memory);
156}
157
158void NpadAbstractButtonHandler::UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag,
159 int style_index, u64 aruid,
160 NpadSharedMemoryEntry& shared_memory) {
161 // TODO
162}
163
164void NpadAbstractButtonHandler::UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag,
165 int style_index, u64 aruid,
166 NpadSharedMemoryEntry& shared_memory) {
167 // TODO
168}
169
170void NpadAbstractButtonHandler::UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag,
171 int style_index, u64 aruid,
172 NpadSharedMemoryEntry& shared_memory) {
173 // TODO
174}
175
176void NpadAbstractButtonHandler::UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag,
177 int style_index, u64 aruid,
178 NpadSharedMemoryEntry& shared_memory) {
179 // TODO
180}
181
182void NpadAbstractButtonHandler::UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag,
183 int style_index, u64 aruid,
184 NpadSharedMemoryEntry& shared_memory) {
185 // TODO
186}
187
188void NpadAbstractButtonHandler::UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag,
189 int style_index, u64 aruid,
190 NpadSharedMemoryEntry& shared_memory) {
191 // TODO
192}
193
194void NpadAbstractButtonHandler::UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int style_index,
195 u64 aruid, NpadSharedMemoryEntry& shared_memory) {
196 // TODO
197}
198
199} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.h b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h
new file mode 100644
index 000000000..01eafe96d
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h
@@ -0,0 +1,75 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Service::HID {
11struct NpadSharedMemoryEntry;
12
13struct AppletResourceHolder;
14class NpadAbstractedPadHolder;
15class NpadAbstractPropertiesHandler;
16
17/// Handles Npad request from HID interfaces
18class NpadAbstractButtonHandler final {
19public:
20 explicit NpadAbstractButtonHandler();
21 ~NpadAbstractButtonHandler();
22
23 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
24 void SetAppletResource(AppletResourceHolder* applet_resource);
25 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
26
27 Result IncrementRefCounter();
28 Result DecrementRefCounter();
29
30 Result UpdateAllButtonWithHomeProtection(u64 aruid);
31
32 void UpdateAllButtonLifo();
33 void UpdateCoreBatteryState();
34 void UpdateButtonState(u64 aruid);
35
36 Result SetHomeProtection(bool is_enabled, u64 aruid);
37 bool IsButtonPressedOnConsoleMode();
38 void EnableCenterClamp();
39
40 void UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid);
41
42 void UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
43 NpadSharedMemoryEntry& shared_memory);
44 void UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
45 NpadSharedMemoryEntry& shared_memory);
46 void UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
47 NpadSharedMemoryEntry& shared_memory);
48 void UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
49 NpadSharedMemoryEntry& shared_memory);
50 void UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
51 NpadSharedMemoryEntry& shared_memory);
52 void UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
53 NpadSharedMemoryEntry& shared_memory);
54 void UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
55 NpadSharedMemoryEntry& shared_memory);
56
57private:
58 struct GcTrigger {
59 float left;
60 float right;
61 };
62
63 AppletResourceHolder* applet_resource_holder{nullptr};
64 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
65 NpadAbstractPropertiesHandler* properties_handler{nullptr};
66
67 s32 ref_counter{};
68
69 bool is_button_pressed_on_console_mode{};
70
71 u64 gc_sampling_number{};
72 GcTrigger gc_trigger_state{};
73};
74
75} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp
new file mode 100644
index 000000000..d4e4181bf
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp
@@ -0,0 +1,126 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/kernel/k_event.h"
5#include "core/hle/kernel/k_readable_event.h"
6#include "hid_core/hid_result.h"
7#include "hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h"
8#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
9#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
10#include "hid_core/resources/npad/npad_types.h"
11
12namespace Service::HID {
13
14NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler() {}
15
16NpadAbstractIrSensorHandler::~NpadAbstractIrSensorHandler() = default;
17
18void NpadAbstractIrSensorHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
19 abstract_pad_holder = holder;
20}
21
22void NpadAbstractIrSensorHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
23 properties_handler = handler;
24}
25
26Result NpadAbstractIrSensorHandler::IncrementRefCounter() {
27 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
28 return ResultNpadHandlerOverflow;
29 }
30 ref_counter++;
31 return ResultSuccess;
32}
33
34Result NpadAbstractIrSensorHandler::DecrementRefCounter() {
35 if (ref_counter == 0) {
36 return ResultNpadHandlerNotInitialized;
37 }
38 ref_counter--;
39 return ResultSuccess;
40}
41
42void NpadAbstractIrSensorHandler::UpdateIrSensorState() {
43 const auto previous_state = sensor_state;
44 std::array<IAbstractedPad*, 5> abstract_pads{};
45 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
46
47 if (count == 0) {
48 sensor_state = NpadIrSensorState::Disabled;
49 if (sensor_state == previous_state) {
50 return;
51 }
52 ir_sensor_event->Signal();
53 return;
54 }
55
56 bool is_found{};
57 for (std::size_t i = 0; i < count; i++) {
58 auto* abstract_pad = abstract_pads[i];
59 if (!abstract_pad->internal_flags.is_connected) {
60 continue;
61 }
62 if (!abstract_pad->disabled_feature_set.has_bluetooth_address) {
63 continue;
64 }
65 is_found = true;
66 xcd_handle = abstract_pad->xcd_handle;
67 }
68
69 if (is_found) {
70 if (sensor_state == NpadIrSensorState::Active) {
71 return;
72 }
73 sensor_state = NpadIrSensorState::Available;
74 if (sensor_state == previous_state) {
75 return;
76 }
77 ir_sensor_event->Signal();
78 return;
79 }
80
81 sensor_state = NpadIrSensorState::Unavailable;
82 if (sensor_state == previous_state) {
83 return;
84 }
85
86 ir_sensor_event->Signal();
87 return;
88}
89
90Result NpadAbstractIrSensorHandler::ActivateIrSensor(bool is_enabled) {
91 if (sensor_state == NpadIrSensorState::Unavailable) {
92 return ResultIrSensorIsNotReady;
93 }
94 if (is_enabled && sensor_state == NpadIrSensorState::Available) {
95 sensor_state = NpadIrSensorState::Active;
96 } else {
97 if (is_enabled) {
98 return ResultSuccess;
99 }
100 if (sensor_state != NpadIrSensorState::Active) {
101 return ResultSuccess;
102 }
103 sensor_state = NpadIrSensorState::Available;
104 }
105 ir_sensor_event->Signal();
106 return ResultSuccess;
107}
108
109Result NpadAbstractIrSensorHandler::GetIrSensorEventHandle(Kernel::KReadableEvent** out_event) {
110 *out_event = &ir_sensor_event->GetReadableEvent();
111 return ResultSuccess;
112}
113
114Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) const {
115 if (sensor_state < NpadIrSensorState::Available) {
116 return ResultIrSensorIsNotReady;
117 }
118 handle = xcd_handle;
119 return ResultSuccess;
120}
121
122NpadIrSensorState NpadAbstractIrSensorHandler::GetSensorState() const {
123 return sensor_state;
124}
125
126} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h
new file mode 100644
index 000000000..fe8e005af
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h
@@ -0,0 +1,56 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Kernel {
11class KEvent;
12class KReadableEvent;
13} // namespace Kernel
14
15enum class NpadIrSensorState : u32 {
16 Disabled,
17 Unavailable,
18 Available,
19 Active,
20};
21
22namespace Service::HID {
23class NpadAbstractedPadHolder;
24class NpadAbstractPropertiesHandler;
25
26/// Handles Npad request from HID interfaces
27class NpadAbstractIrSensorHandler final {
28public:
29 explicit NpadAbstractIrSensorHandler();
30 ~NpadAbstractIrSensorHandler();
31
32 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
33 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
34
35 Result IncrementRefCounter();
36 Result DecrementRefCounter();
37
38 void UpdateIrSensorState();
39 Result ActivateIrSensor(bool param_2);
40
41 Result GetIrSensorEventHandle(Kernel::KReadableEvent** out_event);
42
43 Result GetXcdHandleForNpadWithIrSensor(u64& handle) const;
44
45 NpadIrSensorState GetSensorState() const;
46
47private:
48 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
49 NpadAbstractPropertiesHandler* properties_handler{nullptr};
50
51 s32 ref_counter{};
52 Kernel::KEvent* ir_sensor_event{nullptr};
53 u64 xcd_handle{};
54 NpadIrSensorState sensor_state{};
55};
56} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp
new file mode 100644
index 000000000..0b2bfe88d
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp
@@ -0,0 +1,123 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/core_timing.h"
5#include "hid_core/hid_result.h"
6#include "hid_core/hid_util.h"
7#include "hid_core/resources/abstracted_pad/abstract_led_handler.h"
8#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
9#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
10#include "hid_core/resources/applet_resource.h"
11#include "hid_core/resources/npad/npad_types.h"
12
13namespace Service::HID {
14
15NpadAbstractLedHandler::NpadAbstractLedHandler() {}
16
17NpadAbstractLedHandler::~NpadAbstractLedHandler() = default;
18
19void NpadAbstractLedHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
20 abstract_pad_holder = holder;
21}
22
23void NpadAbstractLedHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
24 applet_resource_holder = applet_resource;
25}
26
27void NpadAbstractLedHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
28 properties_handler = handler;
29}
30
31Result NpadAbstractLedHandler::IncrementRefCounter() {
32 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
33 return ResultNpadHandlerOverflow;
34 }
35 ref_counter++;
36 return ResultSuccess;
37}
38
39Result NpadAbstractLedHandler::DecrementRefCounter() {
40 if (ref_counter == 0) {
41 return ResultNpadHandlerNotInitialized;
42 }
43 ref_counter--;
44 return ResultSuccess;
45}
46
47void NpadAbstractLedHandler::SetNpadLedHandlerLedPattern() {
48 const auto npad_id = properties_handler->GetNpadId();
49
50 switch (npad_id) {
51 case Core::HID::NpadIdType::Player1:
52 left_pattern = Core::HID::LedPattern{1, 0, 0, 0};
53 break;
54 case Core::HID::NpadIdType::Player2:
55 left_pattern = Core::HID::LedPattern{1, 1, 0, 0};
56 break;
57 case Core::HID::NpadIdType::Player3:
58 left_pattern = Core::HID::LedPattern{1, 1, 1, 0};
59 break;
60 case Core::HID::NpadIdType::Player4:
61 left_pattern = Core::HID::LedPattern{1, 1, 1, 1};
62 break;
63 case Core::HID::NpadIdType::Player5:
64 left_pattern = Core::HID::LedPattern{1, 0, 0, 1};
65 break;
66 case Core::HID::NpadIdType::Player6:
67 left_pattern = Core::HID::LedPattern{1, 0, 1, 0};
68 break;
69 case Core::HID::NpadIdType::Player7:
70 left_pattern = Core::HID::LedPattern{1, 0, 1, 1};
71 break;
72 case Core::HID::NpadIdType::Player8:
73 left_pattern = Core::HID::LedPattern{0, 1, 1, 0};
74 break;
75 case Core::HID::NpadIdType::Other:
76 case Core::HID::NpadIdType::Handheld:
77 left_pattern = Core::HID::LedPattern{0, 0, 0, 0};
78 break;
79 default:
80 ASSERT_MSG(false, "Invalid npad id type");
81 break;
82 }
83
84 switch (npad_id) {
85 case Core::HID::NpadIdType::Player1:
86 right_pattern = Core::HID::LedPattern{0, 0, 0, 1};
87 break;
88 case Core::HID::NpadIdType::Player2:
89 right_pattern = Core::HID::LedPattern{0, 1, 1, 1};
90 break;
91 case Core::HID::NpadIdType::Player3:
92 right_pattern = Core::HID::LedPattern{0, 1, 1, 1};
93 break;
94 case Core::HID::NpadIdType::Player4:
95 right_pattern = Core::HID::LedPattern{1, 1, 1, 1};
96 break;
97 case Core::HID::NpadIdType::Player5:
98 right_pattern = Core::HID::LedPattern{1, 0, 0, 1};
99 break;
100 case Core::HID::NpadIdType::Player6:
101 right_pattern = Core::HID::LedPattern{0, 1, 0, 1};
102 break;
103 case Core::HID::NpadIdType::Player7:
104 right_pattern = Core::HID::LedPattern{1, 1, 0, 1};
105 break;
106 case Core::HID::NpadIdType::Player8:
107 right_pattern = Core::HID::LedPattern{0, 1, 1, 0};
108 break;
109 case Core::HID::NpadIdType::Other:
110 case Core::HID::NpadIdType::Handheld:
111 right_pattern = Core::HID::LedPattern{0, 0, 0, 0};
112 break;
113 default:
114 ASSERT_MSG(false, "Invalid npad id type");
115 break;
116 }
117}
118
119void NpadAbstractLedHandler::SetLedBlinkingDevice(Core::HID::LedPattern pattern) {
120 led_blinking = pattern;
121}
122
123} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.h b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h
new file mode 100644
index 000000000..09528129b
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h
@@ -0,0 +1,43 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Service::HID {
11struct AppletResourceHolder;
12class NpadAbstractedPadHolder;
13class NpadAbstractPropertiesHandler;
14
15/// Handles Npad request from HID interfaces
16class NpadAbstractLedHandler final {
17public:
18 explicit NpadAbstractLedHandler();
19 ~NpadAbstractLedHandler();
20
21 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
22 void SetAppletResource(AppletResourceHolder* applet_resource);
23 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
24
25 Result IncrementRefCounter();
26 Result DecrementRefCounter();
27
28 void SetNpadLedHandlerLedPattern();
29
30 void SetLedBlinkingDevice(Core::HID::LedPattern pattern);
31
32private:
33 AppletResourceHolder* applet_resource_holder{nullptr};
34 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
35 NpadAbstractPropertiesHandler* properties_handler{nullptr};
36
37 s32 ref_counter{};
38 Core::HID::LedPattern led_blinking{0, 0, 0, 0};
39 Core::HID::LedPattern left_pattern{0, 0, 0, 0};
40 Core::HID::LedPattern right_pattern{0, 0, 0, 0};
41 u64 led_interval{};
42};
43} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp
new file mode 100644
index 000000000..6f35bd95c
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp
@@ -0,0 +1,108 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/abstracted_pad/abstract_mcu_handler.h"
6#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
7#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
8#include "hid_core/resources/npad/npad_types.h"
9
10namespace Service::HID {
11
12NpadAbstractMcuHandler::NpadAbstractMcuHandler() {}
13
14NpadAbstractMcuHandler::~NpadAbstractMcuHandler() = default;
15
16void NpadAbstractMcuHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
17 abstract_pad_holder = holder;
18}
19
20void NpadAbstractMcuHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
21 properties_handler = handler;
22}
23
24Result NpadAbstractMcuHandler::IncrementRefCounter() {
25 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
26 return ResultNpadHandlerOverflow;
27 }
28 ref_counter++;
29 return ResultSuccess;
30}
31
32Result NpadAbstractMcuHandler::DecrementRefCounter() {
33 if (ref_counter == 0) {
34 return ResultNpadHandlerNotInitialized;
35 }
36 ref_counter--;
37 return ResultSuccess;
38}
39
40void NpadAbstractMcuHandler::UpdateMcuState() {
41 std::array<IAbstractedPad*, 5> abstract_pads{};
42 const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads);
43
44 if (count == 0) {
45 mcu_holder = {};
46 return;
47 }
48
49 for (std::size_t i = 0; i < count; i++) {
50 auto* abstract_pad = abstract_pads[i];
51 if (!abstract_pad->internal_flags.is_connected) {
52 continue;
53 }
54 if (!abstract_pad->disabled_feature_set.has_left_joy_rail_bus) {
55 if (!abstract_pad->disabled_feature_set.has_left_joy_six_axis_sensor &&
56 !abstract_pad->disabled_feature_set.has_right_joy_six_axis_sensor) {
57 continue;
58 }
59 if (mcu_holder[1].state != NpadMcuState::Active) {
60 mcu_holder[1].state = NpadMcuState::Available;
61 }
62 mcu_holder[1].abstracted_pad = abstract_pad;
63 continue;
64 }
65 if (mcu_holder[0].state != NpadMcuState::Active) {
66 mcu_holder[0].state = NpadMcuState::Available;
67 }
68 mcu_holder[0].abstracted_pad = abstract_pad;
69 }
70}
71
72Result NpadAbstractMcuHandler::GetAbstractedPad(IAbstractedPad** data, u32 mcu_index) {
73 if (mcu_holder[mcu_index].state == NpadMcuState::None ||
74 mcu_holder[mcu_index].abstracted_pad == nullptr) {
75 return ResultMcuIsNotReady;
76 }
77 *data = mcu_holder[mcu_index].abstracted_pad;
78 return ResultSuccess;
79}
80
81NpadMcuState NpadAbstractMcuHandler::GetMcuState(u32 mcu_index) {
82 return mcu_holder[mcu_index].state;
83}
84
85Result NpadAbstractMcuHandler::SetMcuState(bool is_enabled, u32 mcu_index) {
86 NpadMcuState& state = mcu_holder[mcu_index].state;
87
88 if (state == NpadMcuState::None) {
89 return ResultMcuIsNotReady;
90 }
91
92 if ((is_enabled) && (state == NpadMcuState::Available)) {
93 state = NpadMcuState::Active;
94 return ResultSuccess;
95 }
96
97 if (is_enabled) {
98 return ResultSuccess;
99 }
100 if (state != NpadMcuState::Active) {
101 return ResultSuccess;
102 }
103
104 state = NpadMcuState::Available;
105 return ResultSuccess;
106}
107
108} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h
new file mode 100644
index 000000000..9902dd03a
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h
@@ -0,0 +1,52 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Service::HID {
11struct IAbstractedPad;
12class NpadAbstractedPadHolder;
13class NpadAbstractPropertiesHandler;
14
15enum class NpadMcuState : u32 {
16 None,
17 Available,
18 Active,
19};
20
21struct NpadMcuHolder {
22 NpadMcuState state;
23 INSERT_PADDING_BYTES(0x4);
24 IAbstractedPad* abstracted_pad;
25};
26static_assert(sizeof(NpadMcuHolder) == 0x10, "NpadMcuHolder is an invalid size");
27
28/// Handles Npad request from HID interfaces
29class NpadAbstractMcuHandler final {
30public:
31 explicit NpadAbstractMcuHandler();
32 ~NpadAbstractMcuHandler();
33
34 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
35 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
36
37 Result IncrementRefCounter();
38 Result DecrementRefCounter();
39
40 void UpdateMcuState();
41 Result GetAbstractedPad(IAbstractedPad** data, u32 mcu_index);
42 NpadMcuState GetMcuState(u32 mcu_index);
43 Result SetMcuState(bool is_enabled, u32 mcu_index);
44
45private:
46 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
47 NpadAbstractPropertiesHandler* properties_handler{nullptr};
48
49 s32 ref_counter{};
50 std::array<NpadMcuHolder, 2> mcu_holder{};
51};
52} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp
new file mode 100644
index 000000000..bd9b79333
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp
@@ -0,0 +1,140 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/kernel/k_event.h"
5#include "core/hle/kernel/k_readable_event.h"
6#include "hid_core/hid_result.h"
7#include "hid_core/resources/abstracted_pad/abstract_nfc_handler.h"
8#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
9#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
10#include "hid_core/resources/npad/npad_types.h"
11
12namespace Service::HID {
13
14NpadAbstractNfcHandler::NpadAbstractNfcHandler() {}
15
16NpadAbstractNfcHandler::~NpadAbstractNfcHandler() = default;
17
18void NpadAbstractNfcHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
19 abstract_pad_holder = holder;
20}
21
22void NpadAbstractNfcHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
23 properties_handler = handler;
24}
25
26Result NpadAbstractNfcHandler::IncrementRefCounter() {
27 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
28 return ResultNpadHandlerOverflow;
29 }
30 ref_counter++;
31 return ResultSuccess;
32}
33
34Result NpadAbstractNfcHandler::DecrementRefCounter() {
35 if (ref_counter == 0) {
36 return ResultNpadHandlerNotInitialized;
37 }
38 ref_counter--;
39 return ResultSuccess;
40}
41
42void NpadAbstractNfcHandler::UpdateNfcState() {
43 std::array<IAbstractedPad*, 5> abstract_pads{};
44 const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads);
45
46 if (count == 0) {
47 if (sensor_state == NpadNfcState::Active) {
48 nfc_activate_event->Signal();
49 }
50 if (sensor_state == NpadNfcState::Unavailable) {
51 return;
52 }
53 sensor_state = NpadNfcState::Unavailable;
54 input_event->Signal();
55 return;
56 }
57
58 bool is_found{};
59 for (std::size_t i = 0; i < count; i++) {
60 auto* abstract_pad = abstract_pads[i];
61 if (!abstract_pad->internal_flags.is_connected) {
62 continue;
63 }
64 if (!abstract_pad->disabled_feature_set.has_nfc) {
65 continue;
66 }
67 is_found = true;
68 xcd_handle = 0;
69 }
70
71 if (is_found) {
72 if (sensor_state == NpadNfcState::Active) {
73 return;
74 }
75 if (sensor_state == NpadNfcState::Available) {
76 return;
77 }
78 sensor_state = NpadNfcState::Available;
79 input_event->Signal();
80 return;
81 }
82
83 if (sensor_state == NpadNfcState::Active) {
84 nfc_activate_event->Signal();
85 }
86 if (sensor_state == NpadNfcState::Unavailable) {
87 return;
88 }
89 sensor_state = NpadNfcState::Unavailable;
90 input_event->Signal();
91 return;
92}
93
94bool NpadAbstractNfcHandler::HasNfcSensor() {
95 return sensor_state != NpadNfcState::Unavailable;
96}
97
98bool NpadAbstractNfcHandler::IsNfcActivated() {
99 return sensor_state == NpadNfcState::Active;
100}
101
102Result NpadAbstractNfcHandler::GetAcquireNfcActivateEventHandle(
103 Kernel::KReadableEvent** out_event) {
104 *out_event = &nfc_activate_event->GetReadableEvent();
105 return ResultSuccess;
106}
107
108void NpadAbstractNfcHandler::SetInputEvent(Kernel::KEvent* event) {
109 input_event = event;
110}
111
112Result NpadAbstractNfcHandler::ActivateNfc(bool is_enabled) {
113 if (sensor_state == NpadNfcState::Active) {
114 return ResultNfcIsNotReady;
115 }
116
117 NpadNfcState new_state = NpadNfcState::Available;
118 if (is_enabled) {
119 new_state = NpadNfcState::Active;
120 }
121 if (sensor_state != new_state) {
122 sensor_state = new_state;
123 nfc_activate_event->Signal();
124 }
125 return ResultSuccess;
126}
127
128Result NpadAbstractNfcHandler::GetXcdHandleWithNfc(u64& out_xcd_handle) const {
129 if (sensor_state == NpadNfcState::Unavailable) {
130 return ResultNfcIsNotReady;
131 }
132 if (xcd_handle == 0) {
133 return ResultNfcXcdHandleIsNotInitialized;
134 }
135
136 out_xcd_handle = xcd_handle;
137 return ResultSuccess;
138}
139
140} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h
new file mode 100644
index 000000000..0702722a6
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h
@@ -0,0 +1,57 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Kernel {
11class KReadableEvent;
12}
13
14enum class NpadNfcState : u32 {
15 Unavailable,
16 Available,
17 Active,
18};
19
20namespace Service::HID {
21class NpadAbstractedPadHolder;
22class NpadAbstractPropertiesHandler;
23
24/// Handles Npad request from HID interfaces
25class NpadAbstractNfcHandler final {
26public:
27 explicit NpadAbstractNfcHandler();
28 ~NpadAbstractNfcHandler();
29
30 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
31 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
32
33 Result IncrementRefCounter();
34 Result DecrementRefCounter();
35
36 void UpdateNfcState();
37 bool HasNfcSensor();
38 bool IsNfcActivated();
39
40 Result GetAcquireNfcActivateEventHandle(Kernel::KReadableEvent** out_event);
41 void SetInputEvent(Kernel::KEvent* event);
42
43 Result ActivateNfc(bool is_enabled);
44
45 Result GetXcdHandleWithNfc(u64& out_xcd_handle) const;
46
47private:
48 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
49 NpadAbstractPropertiesHandler* properties_handler{nullptr};
50
51 s32 ref_counter{};
52 Kernel::KEvent* nfc_activate_event{nullptr};
53 Kernel::KEvent* input_event{nullptr};
54 u64 xcd_handle{};
55 NpadNfcState sensor_state{NpadNfcState::Unavailable};
56};
57} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp
new file mode 100644
index 000000000..2c7691d7c
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp
@@ -0,0 +1,294 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/abstracted_pad/abstract_pad.h"
6#include "hid_core/resources/applet_resource.h"
7#include "hid_core/resources/npad/npad_types.h"
8
9namespace Service::HID {
10
11AbstractPad::AbstractPad() {}
12
13AbstractPad::~AbstractPad() = default;
14
15void AbstractPad::SetExternals(AppletResourceHolder* applet_resource,
16 CaptureButtonResource* capture_button_resource,
17 HomeButtonResource* home_button_resource,
18 SixAxisResource* sixaxis_resource, PalmaResource* palma_resource,
19 VibrationHandler* vibration) {
20 applet_resource_holder = applet_resource;
21
22 properties_handler.SetAppletResource(applet_resource_holder);
23 properties_handler.SetAbstractPadHolder(&abstract_pad_holder);
24
25 led_handler.SetAppletResource(applet_resource_holder);
26 led_handler.SetAbstractPadHolder(&abstract_pad_holder);
27 led_handler.SetPropertiesHandler(&properties_handler);
28
29 ir_sensor_handler.SetAbstractPadHolder(&abstract_pad_holder);
30 ir_sensor_handler.SetPropertiesHandler(&properties_handler);
31
32 nfc_handler.SetAbstractPadHolder(&abstract_pad_holder);
33 nfc_handler.SetPropertiesHandler(&properties_handler);
34
35 mcu_handler.SetAbstractPadHolder(&abstract_pad_holder);
36 mcu_handler.SetPropertiesHandler(&properties_handler);
37
38 std::array<NpadVibrationDevice*, 2> vibration_devices{&vibration_left, &vibration_right};
39 vibration_handler.SetAppletResource(applet_resource_holder);
40 vibration_handler.SetAbstractPadHolder(&abstract_pad_holder);
41 vibration_handler.SetPropertiesHandler(&properties_handler);
42 vibration_handler.SetN64Vibration(&vibration_n64);
43 vibration_handler.SetVibration(vibration_devices);
44 vibration_handler.SetGcVibration(&vibration_gc);
45
46 sixaxis_handler.SetAppletResource(applet_resource_holder);
47 sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder);
48 sixaxis_handler.SetPropertiesHandler(&properties_handler);
49 sixaxis_handler.SetSixaxisResource(sixaxis_resource);
50
51 button_handler.SetAppletResource(applet_resource_holder);
52 button_handler.SetAbstractPadHolder(&abstract_pad_holder);
53 button_handler.SetPropertiesHandler(&properties_handler);
54
55 battery_handler.SetAppletResource(applet_resource_holder);
56 battery_handler.SetAbstractPadHolder(&abstract_pad_holder);
57 battery_handler.SetPropertiesHandler(&properties_handler);
58
59 palma_handler.SetAbstractPadHolder(&abstract_pad_holder);
60 palma_handler.SetPropertiesHandler(&properties_handler);
61 palma_handler.SetPalmaResource(palma_resource);
62}
63
64void AbstractPad::SetNpadId(Core::HID::NpadIdType npad_id) {
65 properties_handler.SetNpadId(npad_id);
66}
67
68Result AbstractPad::Activate() {
69 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
70 return ResultNpadHandlerOverflow;
71 }
72
73 if (ref_counter != 0) {
74 ref_counter++;
75 return ResultSuccess;
76 }
77
78 std::size_t stage = 0;
79 Result result = ResultSuccess;
80
81 if (result.IsSuccess()) {
82 stage++;
83 result = properties_handler.IncrementRefCounter();
84 }
85 if (result.IsSuccess()) {
86 stage++;
87 result = led_handler.IncrementRefCounter();
88 }
89 if (result.IsSuccess()) {
90 stage++;
91 result = ir_sensor_handler.IncrementRefCounter();
92 }
93 if (result.IsSuccess()) {
94 stage++;
95 result = mcu_handler.IncrementRefCounter();
96 }
97 if (result.IsSuccess()) {
98 stage++;
99 result = nfc_handler.IncrementRefCounter();
100 }
101 if (result.IsSuccess()) {
102 stage++;
103 result = vibration_handler.IncrementRefCounter();
104 }
105 if (result.IsSuccess()) {
106 stage++;
107 result = sixaxis_handler.IncrementRefCounter();
108 }
109 if (result.IsSuccess()) {
110 stage++;
111 result = button_handler.IncrementRefCounter();
112 }
113 if (result.IsSuccess()) {
114 stage++;
115 result = battery_handler.IncrementRefCounter();
116 }
117 if (result.IsSuccess()) {
118 stage++;
119 result = palma_handler.IncrementRefCounter();
120 }
121
122 if (result.IsSuccess()) {
123 ref_counter++;
124 return result;
125 }
126
127 if (stage > 9) {
128 battery_handler.DecrementRefCounter();
129 }
130 if (stage > 8) {
131 button_handler.DecrementRefCounter();
132 }
133 if (stage > 7) {
134 sixaxis_handler.DecrementRefCounter();
135 }
136 if (stage > 6) {
137 vibration_handler.DecrementRefCounter();
138 }
139 if (stage > 5) {
140 nfc_handler.DecrementRefCounter();
141 }
142 if (stage > 4) {
143 mcu_handler.DecrementRefCounter();
144 }
145 if (stage > 3) {
146 ir_sensor_handler.DecrementRefCounter();
147 }
148 if (stage > 2) {
149 led_handler.DecrementRefCounter();
150 }
151 if (stage > 1) {
152 properties_handler.DecrementRefCounter();
153 }
154 return result;
155}
156
157Result AbstractPad::Deactivate() {
158 if (ref_counter == 0) {
159 return ResultNpadResourceNotInitialized;
160 }
161
162 ref_counter--;
163 battery_handler.DecrementRefCounter();
164 button_handler.DecrementRefCounter();
165 sixaxis_handler.DecrementRefCounter();
166 vibration_handler.DecrementRefCounter();
167 nfc_handler.DecrementRefCounter();
168 ir_sensor_handler.DecrementRefCounter();
169 mcu_handler.DecrementRefCounter();
170 led_handler.DecrementRefCounter();
171 properties_handler.DecrementRefCounter();
172 palma_handler.DecrementRefCounter();
173
174 return ResultSuccess;
175}
176
177Result AbstractPad::ActivateNpad(u64 aruid) {
178 Result result = ResultSuccess;
179 if (result.IsSuccess()) {
180 result = properties_handler.ActivateNpadUnknown0x88(aruid);
181 }
182 if (result.IsSuccess()) {
183 result = sixaxis_handler.UpdateSixAxisState2(aruid);
184 }
185 if (result.IsSuccess()) {
186 result = battery_handler.UpdateBatteryState(aruid);
187 }
188 return result;
189}
190
191NpadAbstractedPadHolder* AbstractPad::GetAbstractedPadHolder() {
192 return &abstract_pad_holder;
193}
194
195NpadAbstractPropertiesHandler* AbstractPad::GetAbstractPropertiesHandler() {
196 return &properties_handler;
197}
198
199NpadAbstractLedHandler* AbstractPad::GetAbstractLedHandler() {
200 return &led_handler;
201}
202
203NpadAbstractIrSensorHandler* AbstractPad::GetAbstractIrSensorHandler() {
204 return &ir_sensor_handler;
205}
206
207NpadAbstractMcuHandler* AbstractPad::GetAbstractMcuHandler() {
208 return &mcu_handler;
209}
210
211NpadAbstractNfcHandler* AbstractPad::GetAbstractNfcHandler() {
212 return &nfc_handler;
213}
214
215NpadAbstractVibrationHandler* AbstractPad::GetAbstractVibrationHandler() {
216 return &vibration_handler;
217}
218
219NpadAbstractSixAxisHandler* AbstractPad::GetAbstractSixAxisHandler() {
220 return &sixaxis_handler;
221}
222
223NpadAbstractButtonHandler* AbstractPad::GetAbstractButtonHandler() {
224 return &button_handler;
225}
226
227NpadAbstractBatteryHandler* AbstractPad::GetAbstractBatteryHandler() {
228 return &battery_handler;
229}
230
231NpadN64VibrationDevice* AbstractPad::GetN64VibrationDevice() {
232 return &vibration_n64;
233}
234
235NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex device_index) {
236 if (device_index == Core::HID::DeviceIndex::Right) {
237 return &vibration_right;
238 }
239 return &vibration_left;
240}
241
242void AbstractPad::GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list) {
243 list.emplace_back(&vibration_left);
244 list.emplace_back(&vibration_right);
245}
246
247NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() {
248 return &vibration_gc;
249}
250
251Core::HID::NpadIdType AbstractPad::GetLastActiveNpad() {
252 return properties_handler.GetNpadId();
253}
254
255void AbstractPad::UpdateInterfaceType() {
256 if (interface_type != properties_handler.GetInterfaceType()) {
257 Update();
258 }
259 battery_handler.UpdateBatteryState();
260}
261
262void AbstractPad::Update() {
263 properties_handler.UpdateDeviceType();
264 led_handler.SetNpadLedHandlerLedPattern();
265 vibration_handler.UpdateVibrationState();
266 sixaxis_handler.UpdateSixAxisState();
267 nfc_handler.UpdateNfcState();
268 ir_sensor_handler.UpdateIrSensorState();
269 mcu_handler.UpdateMcuState();
270 palma_handler.UpdatePalmaState();
271 battery_handler.UpdateBatteryState();
272 button_handler.EnableCenterClamp();
273
274 interface_type = properties_handler.GetInterfaceType();
275
276 std::scoped_lock lock{*applet_resource_holder->shared_mutex};
277 properties_handler.UpdateAllDeviceProperties();
278 battery_handler.UpdateCoreBatteryState();
279 button_handler.UpdateCoreBatteryState();
280}
281
282void AbstractPad::UpdatePadState() {
283 button_handler.UpdateAllButtonLifo();
284 sixaxis_handler.UpdateSixAxisState();
285 battery_handler.UpdateCoreBatteryState();
286}
287
288void AbstractPad::EnableAppletToGetInput(u64 aruid) {
289 button_handler.UpdateButtonState(aruid);
290 sixaxis_handler.UpdateSixAxisState(aruid);
291 battery_handler.UpdateBatteryState(aruid);
292}
293
294} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h
new file mode 100644
index 000000000..cbdf84af7
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h
@@ -0,0 +1,123 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <mutex>
8
9#include "common/common_types.h"
10#include "core/hle/result.h"
11#include "hid_core/hid_types.h"
12#include "hid_core/resources/applet_resource.h"
13#include "hid_core/resources/npad/npad_types.h"
14
15#include "hid_core/resources/abstracted_pad/abstract_battery_handler.h"
16#include "hid_core/resources/abstracted_pad/abstract_button_handler.h"
17#include "hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h"
18#include "hid_core/resources/abstracted_pad/abstract_led_handler.h"
19#include "hid_core/resources/abstracted_pad/abstract_mcu_handler.h"
20#include "hid_core/resources/abstracted_pad/abstract_nfc_handler.h"
21#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
22#include "hid_core/resources/abstracted_pad/abstract_palma_handler.h"
23#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
24#include "hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h"
25#include "hid_core/resources/abstracted_pad/abstract_vibration_handler.h"
26#include "hid_core/resources/vibration/gc_vibration_device.h"
27#include "hid_core/resources/vibration/n64_vibration_device.h"
28#include "hid_core/resources/vibration/vibration_device.h"
29
30namespace Service::HID {
31class AppletResource;
32class SixAxisResource;
33class PalmaResource;
34class NPadResource;
35class AbstractPad;
36class NpadLastActiveHandler;
37class NpadIrNfcHandler;
38class UniquePads;
39class NpadPalmaHandler;
40class FirmwareResource;
41class NpadVibration;
42class NpadHighestBattery;
43class NpadGcVibration;
44
45class CaptureButtonResource;
46class HomeButtonResource;
47class VibrationHandler;
48
49struct HandheldConfig;
50
51/// Handles Npad request from HID interfaces
52class AbstractPad final {
53public:
54 explicit AbstractPad();
55 ~AbstractPad();
56
57 void SetExternals(AppletResourceHolder* applet_resource,
58 CaptureButtonResource* capture_button_resource,
59 HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource,
60 PalmaResource* palma_resource, VibrationHandler* vibration);
61 void SetNpadId(Core::HID::NpadIdType npad_id);
62
63 Result Activate();
64 Result Deactivate();
65
66 Result ActivateNpad(u64 aruid);
67
68 NpadAbstractedPadHolder* GetAbstractedPadHolder();
69 NpadAbstractPropertiesHandler* GetAbstractPropertiesHandler();
70 NpadAbstractLedHandler* GetAbstractLedHandler();
71 NpadAbstractIrSensorHandler* GetAbstractIrSensorHandler();
72 NpadAbstractMcuHandler* GetAbstractMcuHandler();
73 NpadAbstractNfcHandler* GetAbstractNfcHandler();
74 NpadAbstractVibrationHandler* GetAbstractVibrationHandler();
75 NpadAbstractSixAxisHandler* GetAbstractSixAxisHandler();
76 NpadAbstractButtonHandler* GetAbstractButtonHandler();
77 NpadAbstractBatteryHandler* GetAbstractBatteryHandler();
78
79 NpadN64VibrationDevice* GetN64VibrationDevice();
80 NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index);
81 void GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list);
82 NpadGcVibrationDevice* GetGCVibrationDevice();
83
84 Core::HID::NpadIdType GetLastActiveNpad();
85 void UpdateInterfaceType();
86 void Update();
87
88 void UpdatePadState();
89 void EnableAppletToGetInput(u64 aruid);
90
91private:
92 AppletResourceHolder* applet_resource_holder{nullptr};
93 NpadAbstractedPadHolder abstract_pad_holder{};
94 NpadAbstractPropertiesHandler properties_handler{};
95 NpadAbstractLedHandler led_handler{};
96 NpadAbstractIrSensorHandler ir_sensor_handler{};
97 NpadAbstractNfcHandler nfc_handler{};
98 NpadAbstractMcuHandler mcu_handler{};
99 NpadAbstractVibrationHandler vibration_handler{};
100 NpadAbstractSixAxisHandler sixaxis_handler{};
101 NpadAbstractButtonHandler button_handler{};
102 NpadAbstractBatteryHandler battery_handler{};
103 NpadAbstractPalmaHandler palma_handler{};
104
105 NpadN64VibrationDevice vibration_n64{};
106 NpadVibrationDevice vibration_left{};
107 NpadVibrationDevice vibration_right{};
108 NpadGcVibrationDevice vibration_gc{};
109
110 // SixAxisConfigHolder fullkey_config;
111 // SixAxisConfigHolder handheld_config;
112 // SixAxisConfigHolder dual_left_config;
113 // SixAxisConfigHolder dual_right_config;
114 // SixAxisConfigHolder left_config;
115 // SixAxisConfigHolder right_config;
116
117 s32 ref_counter{};
118 Core::HID::NpadInterfaceType interface_type{Core::HID::NpadInterfaceType::None};
119};
120
121using FullAbstractPad = std::array<AbstractPad, MaxSupportedNpadIdTypes>;
122
123} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp
new file mode 100644
index 000000000..8334dc34f
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp
@@ -0,0 +1,99 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
6#include "hid_core/resources/npad/npad_types.h"
7
8namespace Service::HID {
9
10Result NpadAbstractedPadHolder::RegisterAbstractPad(IAbstractedPad* abstracted_pad) {
11 if (list_size >= assignment_list.size()) {
12 return ResultNpadIsNotProController;
13 }
14
15 for (std::size_t i = 0; i < list_size; i++) {
16 if (assignment_list[i].device_type == abstracted_pad->device_type) {
17 return ResultNpadIsNotProController;
18 }
19 }
20
21 assignment_list[list_size] = {
22 .abstracted_pad = abstracted_pad,
23 .device_type = abstracted_pad->device_type,
24 .interface_type = abstracted_pad->interface_type,
25 .controller_id = abstracted_pad->controller_id,
26 };
27
28 list_size++;
29 return ResultSuccess;
30}
31
32void NpadAbstractedPadHolder::RemoveAbstractPadByControllerId(u64 controller_id) {
33 if (list_size == 0) {
34 return;
35 }
36 if (controller_id == 0) {
37 return;
38 }
39 for (std::size_t i = 0; i < list_size; i++) {
40 if (assignment_list[i].controller_id != controller_id) {
41 continue;
42 }
43 for (std::size_t e = i + 1; e < list_size; e++) {
44 assignment_list[e - 1] = assignment_list[e];
45 }
46 list_size--;
47 return;
48 }
49}
50
51void NpadAbstractedPadHolder::DetachAbstractedPad() {
52 while (list_size > 0) {
53 for (std::size_t i = 1; i < list_size; i++) {
54 assignment_list[i - 1] = assignment_list[i];
55 }
56 list_size--;
57 }
58}
59
60u64 NpadAbstractedPadHolder::RemoveAbstractPadByAssignmentStyle(
61 Service::HID::AssignmentStyle assignment_style) {
62 for (std::size_t i = 0; i < list_size; i++) {
63 if ((assignment_style.raw & assignment_list[i].abstracted_pad->assignment_style.raw) == 0) {
64 continue;
65 }
66 for (std::size_t e = i + 1; e < list_size; e++) {
67 assignment_list[e - 1] = assignment_list[e];
68 }
69 list_size--;
70 return list_size;
71 }
72 return list_size;
73}
74
75u32 NpadAbstractedPadHolder::GetAbstractedPads(std::span<IAbstractedPad*> list) const {
76 u32 num_elements = std::min(static_cast<u32>(list.size()), list_size);
77 for (std::size_t i = 0; i < num_elements; i++) {
78 list[i] = assignment_list[i].abstracted_pad;
79 }
80 return num_elements;
81}
82
83void NpadAbstractedPadHolder::SetAssignmentMode(const NpadJoyAssignmentMode& mode) {
84 assignment_mode = mode;
85}
86
87NpadJoyAssignmentMode NpadAbstractedPadHolder::GetAssignmentMode() const {
88 return assignment_mode;
89}
90
91std::size_t NpadAbstractedPadHolder::GetStyleIndexList(
92 std::span<Core::HID::NpadStyleIndex> list) const {
93 for (std::size_t i = 0; i < list_size; i++) {
94 list[i] = assignment_list[i].device_type;
95 }
96 return list_size;
97}
98
99} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad_holder.h b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.h
new file mode 100644
index 000000000..fb7f472e8
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.h
@@ -0,0 +1,47 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <mutex>
8#include <span>
9
10#include "common/common_types.h"
11#include "core/hle/result.h"
12#include "hid_core/hid_types.h"
13#include "hid_core/resources/npad/npad_types.h"
14
15namespace Service::HID {
16struct IAbstractedPad;
17
18struct AbstractAssignmentHolder {
19 IAbstractedPad* abstracted_pad;
20 Core::HID::NpadStyleIndex device_type;
21 Core::HID::NpadInterfaceType interface_type;
22 INSERT_PADDING_BYTES(0x6);
23 u64 controller_id;
24};
25static_assert(sizeof(AbstractAssignmentHolder) == 0x18,
26 "AbstractAssignmentHolder is an invalid size");
27
28/// This is nn::hid::server::NpadAbstractedPadHolder
29class NpadAbstractedPadHolder final {
30public:
31 Result RegisterAbstractPad(IAbstractedPad* abstracted_pad);
32 void RemoveAbstractPadByControllerId(u64 controller_id);
33 void DetachAbstractedPad();
34 u64 RemoveAbstractPadByAssignmentStyle(Service::HID::AssignmentStyle assignment_style);
35 u32 GetAbstractedPads(std::span<IAbstractedPad*> list) const;
36
37 void SetAssignmentMode(const NpadJoyAssignmentMode& mode);
38 NpadJoyAssignmentMode GetAssignmentMode() const;
39
40 std::size_t GetStyleIndexList(std::span<Core::HID::NpadStyleIndex> list) const;
41
42private:
43 std::array<AbstractAssignmentHolder, 5> assignment_list{};
44 u32 list_size{};
45 NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
46};
47} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp
new file mode 100644
index 000000000..04d276d61
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp
@@ -0,0 +1,47 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/abstracted_pad/abstract_palma_handler.h"
6#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
7
8namespace Service::HID {
9
10NpadAbstractPalmaHandler::NpadAbstractPalmaHandler() {}
11
12NpadAbstractPalmaHandler::~NpadAbstractPalmaHandler() = default;
13
14void NpadAbstractPalmaHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
15 abstract_pad_holder = holder;
16}
17
18void NpadAbstractPalmaHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
19 properties_handler = handler;
20 return;
21}
22
23void NpadAbstractPalmaHandler::SetPalmaResource(PalmaResource* resource) {
24 palma_resource = resource;
25}
26
27Result NpadAbstractPalmaHandler::IncrementRefCounter() {
28 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
29 return ResultNpadHandlerOverflow;
30 }
31 ref_counter++;
32 return ResultSuccess;
33}
34
35Result NpadAbstractPalmaHandler::DecrementRefCounter() {
36 if (ref_counter == 0) {
37 return ResultNpadHandlerNotInitialized;
38 }
39 ref_counter--;
40 return ResultSuccess;
41}
42
43void NpadAbstractPalmaHandler::UpdatePalmaState() {
44 // TODO
45}
46
47} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h
new file mode 100644
index 000000000..fbd2e67e5
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h
@@ -0,0 +1,37 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Service::HID {
11class NpadAbstractedPadHolder;
12class NpadAbstractPropertiesHandler;
13class PalmaResource;
14
15class NpadAbstractPalmaHandler final {
16public:
17 explicit NpadAbstractPalmaHandler();
18 ~NpadAbstractPalmaHandler();
19
20 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
21 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
22 void SetPalmaResource(PalmaResource* resource);
23
24 Result IncrementRefCounter();
25 Result DecrementRefCounter();
26
27 void UpdatePalmaState();
28
29private:
30 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
31 NpadAbstractPropertiesHandler* properties_handler{nullptr};
32 PalmaResource* palma_resource{nullptr};
33
34 s32 ref_counter{};
35};
36
37} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp
new file mode 100644
index 000000000..4897a2784
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp
@@ -0,0 +1,322 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_util.h"
5#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
6#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
7#include "hid_core/resources/applet_resource.h"
8#include "hid_core/resources/npad/npad_resource.h"
9#include "hid_core/resources/npad/npad_types.h"
10#include "hid_core/resources/shared_memory_format.h"
11
12namespace Service::HID {
13
14NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler() {}
15
16NpadAbstractPropertiesHandler::~NpadAbstractPropertiesHandler() = default;
17
18void NpadAbstractPropertiesHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
19 abstract_pad_holder = holder;
20 return;
21}
22
23void NpadAbstractPropertiesHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
24 applet_resource_holder = applet_resource;
25 return;
26}
27
28void NpadAbstractPropertiesHandler::SetNpadId(Core::HID::NpadIdType npad_id) {
29 if (!IsNpadIdValid(npad_id)) {
30 ASSERT_MSG(false, "Invalid npad id");
31 }
32
33 npad_id_type = npad_id;
34}
35
36Core::HID::NpadIdType NpadAbstractPropertiesHandler::GetNpadId() const {
37 return npad_id_type;
38}
39
40Result NpadAbstractPropertiesHandler::IncrementRefCounter() {
41 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
42 return ResultNpadHandlerOverflow;
43 }
44
45 if (ref_counter != 0) {
46 ref_counter++;
47 return ResultSuccess;
48 }
49
50 const auto npad_index = NpadIdTypeToIndex(npad_id_type);
51 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
52 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
53 auto& internal_state =
54 data->shared_memory_format->npad.npad_entry[npad_index].internal_state;
55 if (!data->flag.is_assigned) {
56 continue;
57 }
58 internal_state.fullkey_lifo.buffer_count = 0;
59 internal_state.handheld_lifo.buffer_count = 0;
60 internal_state.joy_dual_lifo.buffer_count = 0;
61 internal_state.joy_left_lifo.buffer_count = 0;
62 internal_state.joy_right_lifo.buffer_count = 0;
63 internal_state.palma_lifo.buffer_count = 0;
64 internal_state.system_ext_lifo.buffer_count = 0;
65 internal_state.gc_trigger_lifo.buffer_count = 0;
66 internal_state.sixaxis_fullkey_lifo.lifo.buffer_count = 0;
67 internal_state.sixaxis_handheld_lifo.lifo.buffer_count = 0;
68 internal_state.sixaxis_dual_left_lifo.lifo.buffer_count = 0;
69 internal_state.sixaxis_dual_right_lifo.lifo.buffer_count = 0;
70 internal_state.sixaxis_left_lifo.lifo.buffer_count = 0;
71 internal_state.sixaxis_right_lifo.lifo.buffer_count = 0;
72
73 internal_state.style_tag = {Core::HID::NpadStyleSet::None};
74 internal_state.assignment_mode = NpadJoyAssignmentMode::Dual;
75 internal_state.joycon_color = {};
76 internal_state.fullkey_color = {};
77
78 internal_state.system_properties.raw = 0;
79 internal_state.button_properties.raw = 0;
80 internal_state.device_type.raw = 0;
81
82 internal_state.battery_level_dual = Core::HID::NpadBatteryLevel::Empty;
83 internal_state.battery_level_left = Core::HID::NpadBatteryLevel::Empty;
84 internal_state.battery_level_right = Core::HID::NpadBatteryLevel::Empty;
85
86 internal_state.applet_footer_type = AppletFooterUiType::None;
87 internal_state.applet_footer_attributes = {};
88 internal_state.lark_type_l_and_main = {};
89 internal_state.lark_type_r = {};
90
91 internal_state.sixaxis_fullkey_properties.is_newly_assigned.Assign(true);
92 internal_state.sixaxis_handheld_properties.is_newly_assigned.Assign(true);
93 internal_state.sixaxis_dual_left_properties.is_newly_assigned.Assign(true);
94 internal_state.sixaxis_dual_right_properties.is_newly_assigned.Assign(true);
95 internal_state.sixaxis_left_properties.is_newly_assigned.Assign(true);
96 internal_state.sixaxis_right_properties.is_newly_assigned.Assign(true);
97 }
98
99 ref_counter++;
100 return ResultSuccess;
101}
102
103Result NpadAbstractPropertiesHandler::DecrementRefCounter() {
104 if (ref_counter == 0) {
105 return ResultNpadHandlerNotInitialized;
106 }
107 ref_counter--;
108 return ResultSuccess;
109}
110
111Result NpadAbstractPropertiesHandler::ActivateNpadUnknown0x88(u64 aruid) {
112 const auto npad_index = NpadIdTypeToIndex(npad_id_type);
113 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
114 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
115 if (!data->flag.is_assigned || data->aruid != aruid) {
116 continue;
117 }
118 UpdateDeviceProperties(aruid, data->shared_memory_format->npad.npad_entry[npad_index]);
119 return ResultSuccess;
120 }
121 return ResultSuccess;
122}
123
124void NpadAbstractPropertiesHandler::UpdateDeviceType() {
125 // TODO
126}
127
128void NpadAbstractPropertiesHandler::UpdateDeviceColor() {
129 // TODO
130}
131
132void NpadAbstractPropertiesHandler::UpdateFooterAttributes() {
133 // TODO
134}
135
136void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() {
137 const auto npad_index = NpadIdTypeToIndex(npad_id_type);
138 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
139 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
140 if (!data->flag.is_assigned) {
141 continue;
142 }
143 auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index];
144 UpdateDeviceProperties(data->aruid, npad_entry);
145 }
146}
147
148Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetFullkeyInterfaceType() {
149 std::array<IAbstractedPad*, 5> abstract_pads{};
150 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
151
152 for (std::size_t i = 0; i < count; i++) {
153 auto* abstract_pad = abstract_pads[i];
154 if (!abstract_pad->internal_flags.is_connected) {
155 continue;
156 }
157 if (abstract_pad->device_type != Core::HID::NpadStyleIndex::Fullkey) {
158 continue;
159 }
160 if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) {
161 // Abort
162 continue;
163 }
164 return abstract_pad->interface_type;
165 }
166
167 return Core::HID::NpadInterfaceType::None;
168}
169
170Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetInterfaceType() {
171 std::array<IAbstractedPad*, 5> abstract_pads{};
172 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
173
174 for (std::size_t i = 0; i < count; i++) {
175 auto* abstract_pad = abstract_pads[i];
176 if (!abstract_pad->internal_flags.is_connected) {
177 continue;
178 }
179 if (!abstract_pad->disabled_feature_set.has_identification_code) {
180 continue;
181 }
182 if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) {
183 // Abort
184 continue;
185 }
186 return abstract_pad->interface_type;
187 }
188 return Core::HID::NpadInterfaceType::None;
189}
190
191Core::HID::NpadStyleSet NpadAbstractPropertiesHandler::GetStyleSet(u64 aruid) {
192 // TODO
193 return Core::HID::NpadStyleSet::None;
194}
195
196std::size_t NpadAbstractPropertiesHandler::GetAbstractedPadsWithStyleTag(
197 std::span<IAbstractedPad*> list, Core::HID::NpadStyleTag style) {
198 std::array<IAbstractedPad*, 5> abstract_pads{};
199 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
200
201 if (count == 0) {
202 return count;
203 }
204
205 bool is_supported_style_set{};
206 const auto result = applet_resource_holder->shared_npad_resource->IsSupportedNpadStyleSet(
207 is_supported_style_set, applet_resource_holder->applet_resource->GetActiveAruid());
208
209 if (!is_supported_style_set || result.IsError()) {
210 for (std::size_t i = 0; i < count; i++) {
211 // TODO
212 }
213 return count;
214 }
215
216 std::size_t filtered_count{};
217 for (std::size_t i = 0; i < count; i++) {
218 auto* abstract_pad = abstract_pads[i];
219 const bool is_enabled = true;
220 if (is_enabled) {
221 list[filtered_count] = abstract_pad;
222 filtered_count++;
223 }
224 }
225
226 return filtered_count;
227}
228
229std::size_t NpadAbstractPropertiesHandler::GetAbstractedPads(std::span<IAbstractedPad*> list) {
230 Core::HID::NpadStyleTag style{
231 GetStyleSet(applet_resource_holder->applet_resource->GetActiveAruid())};
232 return GetAbstractedPadsWithStyleTag(list, style);
233}
234
235AppletFooterUiType NpadAbstractPropertiesHandler::GetAppletFooterUiType() {
236 return applet_ui_type.footer;
237}
238
239AppletDetailedUiType NpadAbstractPropertiesHandler::GetAppletDetailedUiType() {
240 return applet_ui_type;
241}
242
243void NpadAbstractPropertiesHandler::UpdateDeviceProperties(u64 aruid,
244 NpadSharedMemoryEntry& internal_state) {
245 // TODO
246}
247
248Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetNpadInterfaceType() {
249 std::array<IAbstractedPad*, 5> abstract_pads{};
250 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
251
252 for (std::size_t i = 0; i < count; i++) {
253 auto* abstract_pad = abstract_pads[i];
254 if (!abstract_pad->internal_flags.is_connected) {
255 continue;
256 }
257 if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) {
258 // Abort
259 continue;
260 }
261 return abstract_pad->interface_type;
262 }
263
264 return Core::HID::NpadInterfaceType::None;
265}
266
267Result NpadAbstractPropertiesHandler::GetNpadFullKeyGripColor(
268 Core::HID::NpadColor& main_color, Core::HID::NpadColor& sub_color) const {
269 std::array<IAbstractedPad*, 5> abstract_pads{};
270 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
271
272 if (applet_ui_type.footer != AppletFooterUiType::SwitchProController) {
273 return ResultNpadIsNotProController;
274 }
275
276 for (std::size_t i = 0; i < count; i++) {
277 auto* abstract_pad = abstract_pads[i];
278 if (!abstract_pad->internal_flags.is_connected) {
279 continue;
280 }
281 return ResultSuccess;
282 }
283
284 return ResultNpadIsNotProController;
285}
286
287void NpadAbstractPropertiesHandler::GetNpadLeftRightInterfaceType(
288 Core::HID::NpadInterfaceType& out_left_interface,
289 Core::HID::NpadInterfaceType& out_right_interface) const {
290 out_left_interface = Core::HID::NpadInterfaceType::None;
291 out_right_interface = Core::HID::NpadInterfaceType::None;
292
293 std::array<IAbstractedPad*, 5> abstract_pads{};
294 const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
295
296 for (std::size_t i = 0; i < count; i++) {
297 auto* abstract_pad = abstract_pads[i];
298 if (!abstract_pad->internal_flags.is_connected) {
299 continue;
300 }
301 if (abstract_pad->assignment_style.is_external_left_assigned &&
302 abstract_pad->assignment_style.is_handheld_left_assigned) {
303 if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) {
304 // Abort
305 continue;
306 }
307 out_left_interface = abstract_pad->interface_type;
308 continue;
309 }
310 if (abstract_pad->assignment_style.is_external_right_assigned &&
311 abstract_pad->assignment_style.is_handheld_right_assigned) {
312 if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) {
313 // Abort
314 continue;
315 }
316 out_right_interface = abstract_pad->interface_type;
317 continue;
318 }
319 }
320}
321
322} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h
new file mode 100644
index 000000000..fa6827899
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h
@@ -0,0 +1,86 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <span>
7
8#include "common/common_types.h"
9#include "core/hle/result.h"
10#include "hid_core/hid_types.h"
11#include "hid_core/resources/npad/npad_types.h"
12
13namespace Service::HID {
14struct NpadSharedMemoryEntry;
15
16struct AppletResourceHolder;
17class NpadAbstractedPadHolder;
18
19struct ColorProperties {
20 ColorAttribute attribute;
21 Core::HID::NpadControllerColor color;
22 INSERT_PADDING_BYTES(0x4);
23};
24
25/// Handles Npad request from HID interfaces
26class NpadAbstractPropertiesHandler final {
27public:
28 explicit NpadAbstractPropertiesHandler();
29 ~NpadAbstractPropertiesHandler();
30
31 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
32 void SetAppletResource(AppletResourceHolder* applet_resource);
33 void SetNpadId(Core::HID::NpadIdType npad_id);
34
35 Core::HID::NpadIdType GetNpadId() const;
36
37 Result IncrementRefCounter();
38 Result DecrementRefCounter();
39
40 Result ActivateNpadUnknown0x88(u64 aruid);
41
42 void UpdateDeviceType();
43 void UpdateDeviceColor();
44 void UpdateFooterAttributes();
45 void UpdateAllDeviceProperties();
46
47 Core::HID::NpadInterfaceType GetFullkeyInterfaceType();
48 Core::HID::NpadInterfaceType GetInterfaceType();
49
50 Core::HID::NpadStyleSet GetStyleSet(u64 aruid);
51 std::size_t GetAbstractedPadsWithStyleTag(std::span<IAbstractedPad*> list,
52 Core::HID::NpadStyleTag style);
53 std::size_t GetAbstractedPads(std::span<IAbstractedPad*> list);
54
55 AppletFooterUiType GetAppletFooterUiType();
56
57 AppletDetailedUiType GetAppletDetailedUiType();
58
59 void UpdateDeviceProperties(u64 aruid, NpadSharedMemoryEntry& internal_state);
60
61 Core::HID::NpadInterfaceType GetNpadInterfaceType();
62
63 Result GetNpadFullKeyGripColor(Core::HID::NpadColor& main_color,
64 Core::HID::NpadColor& sub_color) const;
65
66 void GetNpadLeftRightInterfaceType(Core::HID::NpadInterfaceType& param_2,
67 Core::HID::NpadInterfaceType& param_3) const;
68
69private:
70 AppletResourceHolder* applet_resource_holder{nullptr};
71 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
72 Core::HID::NpadIdType npad_id_type{Core::HID::NpadIdType::Invalid};
73 s32 ref_counter{};
74 Core::HID::DeviceIndex device_type{};
75 AppletDetailedUiType applet_ui_type{};
76 AppletFooterUiAttributes applet_ui_attributes{};
77 bool is_vertical{};
78 bool is_horizontal{};
79 bool use_plus{};
80 bool use_minus{};
81 bool has_directional_buttons{};
82 ColorProperties fullkey_color{};
83 ColorProperties left_color{};
84 ColorProperties right_color{};
85};
86} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp
new file mode 100644
index 000000000..6d759298e
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp
@@ -0,0 +1,154 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/hid_util.h"
6#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
7#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
8#include "hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h"
9#include "hid_core/resources/applet_resource.h"
10#include "hid_core/resources/npad/npad_types.h"
11#include "hid_core/resources/shared_memory_format.h"
12
13namespace Service::HID {
14
15NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler() {}
16
17NpadAbstractSixAxisHandler::~NpadAbstractSixAxisHandler() = default;
18
19void NpadAbstractSixAxisHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
20 abstract_pad_holder = holder;
21}
22
23void NpadAbstractSixAxisHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
24 applet_resource_holder = applet_resource;
25}
26
27void NpadAbstractSixAxisHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
28 properties_handler = handler;
29}
30
31void NpadAbstractSixAxisHandler::SetSixaxisResource(SixAxisResource* resource) {
32 six_axis_resource = resource;
33}
34
35Result NpadAbstractSixAxisHandler::IncrementRefCounter() {
36 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
37 return ResultNpadHandlerOverflow;
38 }
39 ref_counter++;
40 return ResultSuccess;
41}
42
43Result NpadAbstractSixAxisHandler::DecrementRefCounter() {
44 if (ref_counter == 0) {
45 return ResultNpadHandlerNotInitialized;
46 }
47 ref_counter--;
48 return ResultSuccess;
49}
50
51u64 NpadAbstractSixAxisHandler::IsFirmwareUpdateAvailable() {
52 // TODO
53 return false;
54}
55
56Result NpadAbstractSixAxisHandler::UpdateSixAxisState() {
57 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
58 for (std::size_t i = 0; i < AruidIndexMax; i++) {
59 auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
60 if (data->flag.is_assigned) {
61 continue;
62 }
63 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
64 UpdateSixaxisInternalState(npad_entry, data->aruid,
65 data->flag.enable_six_axis_sensor.As<bool>());
66 }
67 return ResultSuccess;
68}
69
70Result NpadAbstractSixAxisHandler::UpdateSixAxisState(u64 aruid) {
71 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
72 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
73 if (data == nullptr) {
74 return ResultSuccess;
75 }
76 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
77 UpdateSixaxisInternalState(npad_entry, data->aruid,
78 data->flag.enable_six_axis_sensor.As<bool>());
79 return ResultSuccess;
80}
81
82Result NpadAbstractSixAxisHandler::UpdateSixAxisState2(u64 aruid) {
83 const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId());
84 AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid);
85 if (aruid_data == nullptr) {
86 return ResultSuccess;
87 }
88 auto& npad_internal_state = aruid_data->shared_memory_format->npad.npad_entry[npad_index];
89 UpdateSixaxisInternalState(npad_internal_state, aruid,
90 aruid_data->flag.enable_six_axis_sensor.As<bool>());
91 return ResultSuccess;
92}
93
94void NpadAbstractSixAxisHandler::UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry,
95 u64 aruid, bool is_sensor_enabled) {
96 const Core::HID::NpadStyleTag style_tag{properties_handler->GetStyleSet(aruid)};
97
98 if (!style_tag.palma) {
99 UpdateSixaxisFullkeyLifo(style_tag, npad_entry.internal_state.sixaxis_fullkey_lifo,
100 is_sensor_enabled);
101 } else {
102 UpdateSixAxisPalmaLifo(style_tag, npad_entry.internal_state.sixaxis_fullkey_lifo,
103 is_sensor_enabled);
104 }
105 UpdateSixaxisHandheldLifo(style_tag, npad_entry.internal_state.sixaxis_handheld_lifo,
106 is_sensor_enabled);
107 UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_left_lifo,
108 is_sensor_enabled);
109 UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_right_lifo,
110 is_sensor_enabled);
111 UpdateSixaxisLeftLifo(style_tag, npad_entry.internal_state.sixaxis_left_lifo,
112 is_sensor_enabled);
113 UpdateSixaxisRightLifo(style_tag, npad_entry.internal_state.sixaxis_right_lifo,
114 is_sensor_enabled);
115 // TODO: Set sixaxis properties
116}
117
118void NpadAbstractSixAxisHandler::UpdateSixaxisFullkeyLifo(Core::HID::NpadStyleTag style_tag,
119 NpadSixAxisSensorLifo& sensor_lifo,
120 bool is_sensor_enabled) {
121 // TODO
122}
123
124void NpadAbstractSixAxisHandler::UpdateSixAxisPalmaLifo(Core::HID::NpadStyleTag style_tag,
125 NpadSixAxisSensorLifo& sensor_lifo,
126 bool is_sensor_enabled) {
127 // TODO
128}
129
130void NpadAbstractSixAxisHandler::UpdateSixaxisHandheldLifo(Core::HID::NpadStyleTag style_tag,
131 NpadSixAxisSensorLifo& sensor_lifo,
132 bool is_sensor_enabled) {
133 // TODO
134}
135
136void NpadAbstractSixAxisHandler::UpdateSixaxisDualLifo(Core::HID::NpadStyleTag style_tag,
137 NpadSixAxisSensorLifo& sensor_lifo,
138 bool is_sensor_enabled) {
139 // TODO
140}
141
142void NpadAbstractSixAxisHandler::UpdateSixaxisLeftLifo(Core::HID::NpadStyleTag style_tag,
143 NpadSixAxisSensorLifo& sensor_lifo,
144 bool is_sensor_enabled) {
145 // TODO
146}
147
148void NpadAbstractSixAxisHandler::UpdateSixaxisRightLifo(Core::HID::NpadStyleTag style_tag,
149 NpadSixAxisSensorLifo& sensor_lifo,
150 bool is_sensor_enabled) {
151 // TODO
152}
153
154} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h
new file mode 100644
index 000000000..9c20459e9
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h
@@ -0,0 +1,61 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8#include "hid_core/hid_types.h"
9
10namespace Service::HID {
11class SixAxisResource;
12struct AppletResourceHolder;
13class NpadAbstractedPadHolder;
14class NpadAbstractPropertiesHandler;
15struct NpadSixAxisSensorLifo;
16
17/// Handles Npad request from HID interfaces
18class NpadAbstractSixAxisHandler final {
19public:
20 explicit NpadAbstractSixAxisHandler();
21 ~NpadAbstractSixAxisHandler();
22
23 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
24 void SetAppletResource(AppletResourceHolder* applet_resource);
25 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
26 void SetSixaxisResource(SixAxisResource* resource);
27
28 Result IncrementRefCounter();
29 Result DecrementRefCounter();
30
31 u64 IsFirmwareUpdateAvailable();
32
33 Result UpdateSixAxisState();
34 Result UpdateSixAxisState(u64 aruid);
35 Result UpdateSixAxisState2(u64 aruid);
36
37private:
38 void UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry, u64 aruid,
39 bool is_sensor_enabled);
40 void UpdateSixaxisFullkeyLifo(Core::HID::NpadStyleTag style_tag,
41 NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
42 void UpdateSixAxisPalmaLifo(Core::HID::NpadStyleTag style_tag,
43 NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
44 void UpdateSixaxisHandheldLifo(Core::HID::NpadStyleTag style_tag,
45 NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
46 void UpdateSixaxisDualLifo(Core::HID::NpadStyleTag style_tag,
47 NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
48 void UpdateSixaxisLeftLifo(Core::HID::NpadStyleTag style_tag,
49 NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
50 void UpdateSixaxisRightLifo(Core::HID::NpadStyleTag style_tag,
51 NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
52
53 AppletResourceHolder* applet_resource_holder{nullptr};
54 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
55 NpadAbstractPropertiesHandler* properties_handler{nullptr};
56 SixAxisResource* six_axis_resource{nullptr};
57
58 s32 ref_counter{};
59};
60
61} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp
new file mode 100644
index 000000000..a00d6c9de
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp
@@ -0,0 +1,73 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/hid_util.h"
6#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
7#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
8#include "hid_core/resources/abstracted_pad/abstract_vibration_handler.h"
9#include "hid_core/resources/applet_resource.h"
10#include "hid_core/resources/npad/npad_vibration.h"
11#include "hid_core/resources/vibration/gc_vibration_device.h"
12#include "hid_core/resources/vibration/n64_vibration_device.h"
13#include "hid_core/resources/vibration/vibration_device.h"
14
15namespace Service::HID {
16
17NpadAbstractVibrationHandler::NpadAbstractVibrationHandler() {}
18
19NpadAbstractVibrationHandler::~NpadAbstractVibrationHandler() = default;
20
21void NpadAbstractVibrationHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
22 abstract_pad_holder = holder;
23}
24
25void NpadAbstractVibrationHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
26 applet_resource_holder = applet_resource;
27}
28
29void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
30 properties_handler = handler;
31}
32
33void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) {
34 n64_vibration_device = n64_device;
35}
36
37void NpadAbstractVibrationHandler::SetVibration(std::span<NpadVibrationDevice*> device) {
38 for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) {
39 vibration_device[i] = device[i];
40 }
41}
42
43void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) {
44 gc_vibration_device = gc_device;
45}
46
47Result NpadAbstractVibrationHandler::IncrementRefCounter() {
48 if (ref_counter == std::numeric_limits<s32>::max() - 1) {
49 return ResultNpadHandlerOverflow;
50 }
51 ref_counter++;
52 return ResultSuccess;
53}
54
55Result NpadAbstractVibrationHandler::DecrementRefCounter() {
56 if (ref_counter == 0) {
57 return ResultNpadHandlerNotInitialized;
58 }
59 ref_counter--;
60 return ResultSuccess;
61}
62
63void NpadAbstractVibrationHandler::UpdateVibrationState() {
64 const bool is_handheld_hid_enabled =
65 applet_resource_holder->handheld_config->is_handheld_hid_enabled;
66 const bool is_force_handheld_style_vibration =
67 applet_resource_holder->handheld_config->is_force_handheld_style_vibration;
68
69 if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) {
70 // TODO
71 }
72}
73} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h
new file mode 100644
index 000000000..aeb07ce86
--- /dev/null
+++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h
@@ -0,0 +1,51 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <span>
7
8#include "common/common_types.h"
9#include "core/hle/result.h"
10#include "hid_core/hid_types.h"
11
12namespace Service::HID {
13struct AppletResourceHolder;
14class NpadAbstractedPadHolder;
15class NpadAbstractPropertiesHandler;
16class NpadGcVibrationDevice;
17class NpadVibrationDevice;
18class NpadN64VibrationDevice;
19class NpadVibration;
20
21/// Keeps track of battery levels and updates npad battery shared memory values
22class NpadAbstractVibrationHandler final {
23public:
24 explicit NpadAbstractVibrationHandler();
25 ~NpadAbstractVibrationHandler();
26
27 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
28 void SetAppletResource(AppletResourceHolder* applet_resource);
29 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
30
31 void SetN64Vibration(NpadN64VibrationDevice* n64_device);
32 void SetVibration(std::span<NpadVibrationDevice*> device);
33 void SetGcVibration(NpadGcVibrationDevice* gc_device);
34
35 Result IncrementRefCounter();
36 Result DecrementRefCounter();
37
38 void UpdateVibrationState();
39
40private:
41 AppletResourceHolder* applet_resource_holder{nullptr};
42 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
43 NpadAbstractPropertiesHandler* properties_handler{nullptr};
44
45 NpadN64VibrationDevice* n64_vibration_device{nullptr};
46 std::array<NpadVibrationDevice*, 2> vibration_device{};
47 NpadGcVibrationDevice* gc_vibration_device{nullptr};
48 NpadVibration* vibration_handler{nullptr};
49 s32 ref_counter{};
50};
51} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp
index 1f8a0f8ab..97537a2e2 100644
--- a/src/hid_core/resources/npad/npad.cpp
+++ b/src/hid_core/resources/npad/npad.cpp
@@ -193,7 +193,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) {
193 case Core::HID::NpadStyleIndex::None: 193 case Core::HID::NpadStyleIndex::None:
194 ASSERT(false); 194 ASSERT(false);
195 break; 195 break;
196 case Core::HID::NpadStyleIndex::ProController: 196 case Core::HID::NpadStyleIndex::Fullkey:
197 shared_memory->fullkey_color.attribute = ColorAttribute::Ok; 197 shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
198 shared_memory->fullkey_color.fullkey = body_colors.fullkey; 198 shared_memory->fullkey_color.fullkey = body_colors.fullkey;
199 shared_memory->battery_level_dual = battery_level.dual.battery_level; 199 shared_memory->battery_level_dual = battery_level.dual.battery_level;
@@ -491,7 +491,7 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
491 case Core::HID::NpadStyleIndex::None: 491 case Core::HID::NpadStyleIndex::None:
492 ASSERT(false); 492 ASSERT(false);
493 break; 493 break;
494 case Core::HID::NpadStyleIndex::ProController: 494 case Core::HID::NpadStyleIndex::Fullkey:
495 case Core::HID::NpadStyleIndex::NES: 495 case Core::HID::NpadStyleIndex::NES:
496 case Core::HID::NpadStyleIndex::SNES: 496 case Core::HID::NpadStyleIndex::SNES:
497 case Core::HID::NpadStyleIndex::N64: 497 case Core::HID::NpadStyleIndex::N64:
@@ -1292,7 +1292,7 @@ Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1292 u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 1292 u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1293 auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); 1293 auto& controller = GetControllerFromHandle(aruid, sixaxis_handle);
1294 switch (sixaxis_handle.npad_type) { 1294 switch (sixaxis_handle.npad_type) {
1295 case Core::HID::NpadStyleIndex::ProController: 1295 case Core::HID::NpadStyleIndex::Fullkey:
1296 case Core::HID::NpadStyleIndex::Pokeball: 1296 case Core::HID::NpadStyleIndex::Pokeball:
1297 return controller.shared_memory->sixaxis_fullkey_properties; 1297 return controller.shared_memory->sixaxis_fullkey_properties;
1298 case Core::HID::NpadStyleIndex::Handheld: 1298 case Core::HID::NpadStyleIndex::Handheld:
@@ -1315,7 +1315,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1315 u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { 1315 u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
1316 const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); 1316 const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle);
1317 switch (sixaxis_handle.npad_type) { 1317 switch (sixaxis_handle.npad_type) {
1318 case Core::HID::NpadStyleIndex::ProController: 1318 case Core::HID::NpadStyleIndex::Fullkey:
1319 case Core::HID::NpadStyleIndex::Pokeball: 1319 case Core::HID::NpadStyleIndex::Pokeball:
1320 return controller.shared_memory->sixaxis_fullkey_properties; 1320 return controller.shared_memory->sixaxis_fullkey_properties;
1321 case Core::HID::NpadStyleIndex::Handheld: 1321 case Core::HID::NpadStyleIndex::Handheld:
diff --git a/src/hid_core/resources/npad/npad_data.cpp b/src/hid_core/resources/npad/npad_data.cpp
index c7e9760cb..29ad5cb08 100644
--- a/src/hid_core/resources/npad/npad_data.cpp
+++ b/src/hid_core/resources/npad/npad_data.cpp
@@ -151,7 +151,7 @@ Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const {
151bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { 151bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const {
152 Core::HID::NpadStyleTag style = {supported_npad_style_set}; 152 Core::HID::NpadStyleTag style = {supported_npad_style_set};
153 switch (style_index) { 153 switch (style_index) {
154 case Core::HID::NpadStyleIndex::ProController: 154 case Core::HID::NpadStyleIndex::Fullkey:
155 return style.fullkey.As<bool>(); 155 return style.fullkey.As<bool>();
156 case Core::HID::NpadStyleIndex::Handheld: 156 case Core::HID::NpadStyleIndex::Handheld:
157 return style.handheld.As<bool>(); 157 return style.handheld.As<bool>();
diff --git a/src/hid_core/resources/npad/npad_types.h b/src/hid_core/resources/npad/npad_types.h
index a02f9cf16..074dd40cf 100644
--- a/src/hid_core/resources/npad/npad_types.h
+++ b/src/hid_core/resources/npad/npad_types.h
@@ -252,4 +252,103 @@ enum class NpadLagerType : u32 {
252 U, 252 U,
253}; 253};
254 254
255// nn::hidtypes::FeatureType
256struct FeatureType {
257 union {
258 u64 raw{};
259 BitField<0, 1, u64> has_left_analog_stick;
260 BitField<1, 1, u64> has_right_analog_stick;
261 BitField<2, 1, u64> has_left_joy_six_axis_sensor;
262 BitField<3, 1, u64> has_right_joy_six_axis_sensor;
263 BitField<4, 1, u64> has_fullkey_joy_six_axis_sensor;
264 BitField<5, 1, u64> has_left_lra_vibration_device;
265 BitField<6, 1, u64> has_right_lra_vibration_device;
266 BitField<7, 1, u64> has_gc_vibration_device;
267 BitField<8, 1, u64> has_erm_vibration_device;
268 BitField<9, 1, u64> has_left_joy_rail_bus;
269 BitField<10, 1, u64> has_right_joy_rail_bus;
270 BitField<11, 1, u64> has_internal_bus;
271 BitField<12, 1, u64> is_palma;
272 BitField<13, 1, u64> has_nfc;
273 BitField<14, 1, u64> has_ir_sensor;
274 BitField<15, 1, u64> is_analog_stick_calibration_supported;
275 BitField<16, 1, u64> is_six_axis_Sensor_user_calibration_supported;
276 BitField<17, 1, u64> has_left_right_joy_battery;
277 BitField<18, 1, u64> has_fullkey_battery;
278 BitField<19, 1, u64> is_disconnect_controller_if_battery_none;
279 BitField<20, 1, u64> has_controller_color;
280 BitField<21, 1, u64> has_grip_color;
281 BitField<22, 1, u64> has_identification_code;
282 BitField<23, 1, u64> has_bluetooth_address;
283 BitField<24, 1, u64> has_mcu;
284 BitField<25, 1, u64> has_notification_led;
285 BitField<26, 1, u64> has_directional_buttons;
286 BitField<27, 1, u64> has_indicator_led;
287 BitField<28, 1, u64> is_button_config_embedded_supported;
288 BitField<29, 1, u64> is_button_config_full_supported;
289 BitField<30, 1, u64> is_button_config_left_supported;
290 BitField<31, 1, u64> is_button_config_right_supported;
291 BitField<32, 1, u64> is_usb_hid_device;
292 BitField<33, 1, u64> is_kuina_device;
293 BitField<34, 1, u64> is_direct_usb_to_bt_switching_device;
294 BitField<35, 1, u64> is_normalize_analog_stick_with_inner_cross;
295 };
296};
297static_assert(sizeof(FeatureType) == 8, "FeatureType is an invalid size");
298
299// This is nn::hid::AssignmentStyle
300struct AssignmentStyle {
301 union {
302 u32 raw{};
303 BitField<0, 1, u32> is_external_assigned;
304 BitField<1, 1, u32> is_external_left_assigned;
305 BitField<2, 1, u32> is_external_right_assigned;
306 BitField<3, 1, u32> is_handheld_assigned;
307 BitField<4, 1, u32> is_handheld_left_assigned;
308 BitField<5, 1, u32> is_handheld_right_assigned;
309 };
310};
311static_assert(sizeof(AssignmentStyle) == 4, "AssignmentStyle is an invalid size");
312
313// This is nn::hid::server::IAbstractedPad::InternalFlags
314struct InternalFlags {
315 union {
316 u32 raw{};
317 BitField<0, 1, u32> is_bound;
318 BitField<1, 1, u32> is_connected;
319 BitField<2, 1, u32> is_battery_low_ovln_required;
320 BitField<3, 1, u32> is_battery_low_ovln_delay_required;
321 BitField<4, 1, u32> is_sample_recieved;
322 BitField<5, 1, u32> is_virtual_input;
323 BitField<6, 1, u32> is_wired;
324 BitField<8, 1, u32> use_center_clamp;
325 BitField<9, 1, u32> has_virtual_six_axis_sensor_acceleration;
326 BitField<10, 1, u32> has_virtual_six_axis_sensor_angle;
327 BitField<11, 1, u32> is_debug_pad;
328 };
329};
330static_assert(sizeof(InternalFlags) == 4, "InternalFlags is an invalid size");
331
332/// This is nn::hid::server::IAbstractedPad
333struct IAbstractedPad {
334 InternalFlags internal_flags;
335 u64 controller_id;
336 u32 controller_number;
337 u64 low_battery_display_delay_time;
338 u64 low_battery_display_delay_interval;
339 FeatureType feature_set;
340 FeatureType disabled_feature_set;
341 AssignmentStyle assignment_style;
342 Core::HID::NpadStyleIndex device_type;
343 Core::HID::NpadInterfaceType interface_type;
344 Core::HID::NpadPowerInfo power_info;
345 u32 pad_state;
346 u32 button_mask;
347 u32 system_button_mask;
348 u8 indicator;
349 std::vector<f32> virtual_six_axis_sensor_acceleration;
350 std::vector<f32> virtual_six_axis_sensor_angle;
351 u64 xcd_handle;
352 u64 color;
353};
255} // namespace Service::HID 354} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad_vibration.cpp b/src/hid_core/resources/npad/npad_vibration.cpp
new file mode 100644
index 000000000..3bdd55dec
--- /dev/null
+++ b/src/hid_core/resources/npad/npad_vibration.cpp
@@ -0,0 +1,80 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_vibration.h"
6
7namespace Service::HID {
8
9NpadVibration::NpadVibration() {}
10
11NpadVibration::~NpadVibration() = default;
12
13Result NpadVibration::Activate() {
14 std::scoped_lock lock{mutex};
15
16 const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
17 // if (master_volume < 0.0f || master_volume > 1.0f) {
18 // return ResultVibrationStrenghtOutOfRange;
19 // }
20
21 volume = master_volume;
22 return ResultSuccess;
23}
24
25Result NpadVibration::Deactivate() {
26 return ResultSuccess;
27}
28
29Result NpadVibration::SetVibrationMasterVolume(f32 master_volume) {
30 std::scoped_lock lock{mutex};
31
32 if (master_volume < 0.0f && master_volume > 1.0f) {
33 return ResultVibrationStrenghtOutOfRange;
34 }
35
36 volume = master_volume;
37 // nn::settings::system::SetVibrationMasterVolume(master_volume);
38
39 return ResultSuccess;
40}
41
42Result NpadVibration::GetVibrationVolume(f32& out_volume) const {
43 std::scoped_lock lock{mutex};
44 out_volume = volume;
45 return ResultSuccess;
46}
47
48Result NpadVibration::GetVibrationMasterVolume(f32& out_volume) const {
49 std::scoped_lock lock{mutex};
50
51 const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
52 // if (master_volume < 0.0f || master_volume > 1.0f) {
53 // return ResultVibrationStrenghtOutOfRange;
54 // }
55
56 out_volume = master_volume;
57 return ResultSuccess;
58}
59
60Result NpadVibration::BeginPermitVibrationSession(u64 aruid) {
61 std::scoped_lock lock{mutex};
62 session_aruid = aruid;
63 volume = 1.0;
64 return ResultSuccess;
65}
66
67Result NpadVibration::EndPermitVibrationSession() {
68 std::scoped_lock lock{mutex};
69
70 const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
71 // if (master_volume < 0.0f || master_volume > 1.0f) {
72 // return ResultVibrationStrenghtOutOfRange;
73 // }
74
75 volume = master_volume;
76 session_aruid = 0;
77 return ResultSuccess;
78}
79
80} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad_vibration.h b/src/hid_core/resources/npad/npad_vibration.h
new file mode 100644
index 000000000..0748aeffc
--- /dev/null
+++ b/src/hid_core/resources/npad/npad_vibration.h
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <mutex>
7
8#include "common/common_types.h"
9#include "core/hle/result.h"
10
11namespace Service::HID {
12
13class NpadVibration final {
14public:
15 explicit NpadVibration();
16 ~NpadVibration();
17
18 Result Activate();
19 Result Deactivate();
20
21 Result SetVibrationMasterVolume(f32 master_volume);
22 Result GetVibrationVolume(f32& out_volume) const;
23 Result GetVibrationMasterVolume(f32& out_volume) const;
24
25 Result BeginPermitVibrationSession(u64 aruid);
26 Result EndPermitVibrationSession();
27
28private:
29 f32 volume{};
30 u64 session_aruid{};
31 mutable std::mutex mutex;
32};
33
34} // namespace Service::HID
diff --git a/src/hid_core/resources/six_axis/six_axis.cpp b/src/hid_core/resources/six_axis/six_axis.cpp
index 8a9677c50..da12d2d5a 100644
--- a/src/hid_core/resources/six_axis/six_axis.cpp
+++ b/src/hid_core/resources/six_axis/six_axis.cpp
@@ -114,7 +114,7 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
114 case Core::HID::NpadStyleIndex::None: 114 case Core::HID::NpadStyleIndex::None:
115 ASSERT(false); 115 ASSERT(false);
116 break; 116 break;
117 case Core::HID::NpadStyleIndex::ProController: 117 case Core::HID::NpadStyleIndex::Fullkey:
118 set_motion_state(sixaxis_fullkey_state, motion_state[0]); 118 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
119 break; 119 break;
120 case Core::HID::NpadStyleIndex::Handheld: 120 case Core::HID::NpadStyleIndex::Handheld:
@@ -345,7 +345,7 @@ SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
345 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 345 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
346 auto& controller = GetControllerFromHandle(sixaxis_handle); 346 auto& controller = GetControllerFromHandle(sixaxis_handle);
347 switch (sixaxis_handle.npad_type) { 347 switch (sixaxis_handle.npad_type) {
348 case Core::HID::NpadStyleIndex::ProController: 348 case Core::HID::NpadStyleIndex::Fullkey:
349 case Core::HID::NpadStyleIndex::Pokeball: 349 case Core::HID::NpadStyleIndex::Pokeball:
350 return controller.sixaxis_fullkey; 350 return controller.sixaxis_fullkey;
351 case Core::HID::NpadStyleIndex::Handheld: 351 case Core::HID::NpadStyleIndex::Handheld:
@@ -368,7 +368,7 @@ const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
368 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { 368 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
369 const auto& controller = GetControllerFromHandle(sixaxis_handle); 369 const auto& controller = GetControllerFromHandle(sixaxis_handle);
370 switch (sixaxis_handle.npad_type) { 370 switch (sixaxis_handle.npad_type) {
371 case Core::HID::NpadStyleIndex::ProController: 371 case Core::HID::NpadStyleIndex::Fullkey:
372 case Core::HID::NpadStyleIndex::Pokeball: 372 case Core::HID::NpadStyleIndex::Pokeball:
373 return controller.sixaxis_fullkey; 373 return controller.sixaxis_fullkey;
374 case Core::HID::NpadStyleIndex::Handheld: 374 case Core::HID::NpadStyleIndex::Handheld:
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.cpp b/src/hid_core/resources/vibration/gc_vibration_device.cpp
new file mode 100644
index 000000000..f01f81b9a
--- /dev/null
+++ b/src/hid_core/resources/vibration/gc_vibration_device.cpp
@@ -0,0 +1,106 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h"
7#include "hid_core/resources/vibration/gc_vibration_device.h"
8
9namespace Service::HID {
10
11NpadGcVibrationDevice::NpadGcVibrationDevice() {}
12
13Result NpadGcVibrationDevice::IncrementRefCounter() {
14 if (ref_counter == 0 && is_mounted) {
15 f32 volume = 1.0f;
16 const auto result = vibration_handler->GetVibrationVolume(volume);
17 if (result.IsSuccess()) {
18 // TODO: SendVibrationGcErmCommand
19 }
20 }
21 ref_counter++;
22 return ResultSuccess;
23}
24
25Result NpadGcVibrationDevice::DecrementRefCounter() {
26 if (ref_counter == 1 && !is_mounted) {
27 f32 volume = 1.0f;
28 const auto result = vibration_handler->GetVibrationVolume(volume);
29 if (result.IsSuccess()) {
30 // TODO: SendVibrationGcErmCommand
31 }
32 }
33
34 if (ref_counter > 0) {
35 ref_counter--;
36 }
37
38 return ResultSuccess;
39}
40
41Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) {
42 if (!is_mounted) {
43 return ResultSuccess;
44 }
45 f32 volume = 1.0f;
46 const auto result = vibration_handler->GetVibrationVolume(volume);
47 if (result.IsError()) {
48 return result;
49 }
50 if (volume == 0.0) {
51 command = Core::HID::VibrationGcErmCommand::Stop;
52 } else {
53 if (command > Core::HID::VibrationGcErmCommand::StopHard) {
54 // Abort
55 return ResultSuccess;
56 }
57 }
58 // TODO: SendVibrationGcErmCommand
59 return ResultSuccess;
60}
61
62Result NpadGcVibrationDevice::GetActualVibrationGcErmCommand(
63 Core::HID::VibrationGcErmCommand& out_command) {
64 if (!is_mounted) {
65 out_command = Core::HID::VibrationGcErmCommand::Stop;
66 return ResultSuccess;
67 }
68
69 f32 volume = 1.0f;
70 const auto result = vibration_handler->GetVibrationVolume(volume);
71 if (result.IsError()) {
72 return result;
73 }
74 if (volume == 0.0f) {
75 out_command = Core::HID::VibrationGcErmCommand::Stop;
76 return ResultSuccess;
77 }
78
79 // TODO: GetActualVibrationGcErmCommand
80 return ResultSuccess;
81}
82
83Result NpadGcVibrationDevice::SendVibrationNotificationPattern(
84 Core::HID::VibrationGcErmCommand command) {
85 if (!is_mounted) {
86 return ResultSuccess;
87 }
88
89 f32 volume = 1.0f;
90 const auto result = vibration_handler->GetVibrationVolume(volume);
91 if (result.IsError()) {
92 return result;
93 }
94 if (volume <= 0.0f) {
95 command = Core::HID::VibrationGcErmCommand::Stop;
96 }
97 if (command > Core::HID::VibrationGcErmCommand::StopHard) {
98 // Abort
99 return ResultSuccess;
100 }
101
102 // TODO: SendVibrationNotificationPattern
103 return ResultSuccess;
104}
105
106} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.h b/src/hid_core/resources/vibration/gc_vibration_device.h
new file mode 100644
index 000000000..87abca57d
--- /dev/null
+++ b/src/hid_core/resources/vibration/gc_vibration_device.h
@@ -0,0 +1,31 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <mutex>
8
9#include "common/common_types.h"
10#include "core/hle/result.h"
11#include "hid_core/hid_types.h"
12#include "hid_core/resources/npad/npad_types.h"
13#include "hid_core/resources/vibration/vibration_base.h"
14
15namespace Service::HID {
16class NpadVibration;
17
18/// Handles Npad request from HID interfaces
19class NpadGcVibrationDevice final : public NpadVibrationBase {
20public:
21 explicit NpadGcVibrationDevice();
22
23 Result IncrementRefCounter() override;
24 Result DecrementRefCounter() override;
25
26 Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command);
27
28 Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command);
29 Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command);
30};
31} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.cpp b/src/hid_core/resources/vibration/n64_vibration_device.cpp
new file mode 100644
index 000000000..639f87abf
--- /dev/null
+++ b/src/hid_core/resources/vibration/n64_vibration_device.cpp
@@ -0,0 +1,80 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h"
7#include "hid_core/resources/vibration/n64_vibration_device.h"
8
9namespace Service::HID {
10
11NpadN64VibrationDevice::NpadN64VibrationDevice() {}
12
13Result NpadN64VibrationDevice::IncrementRefCounter() {
14 if (ref_counter == 0 && is_mounted) {
15 f32 volume = 1.0f;
16 const auto result = vibration_handler->GetVibrationVolume(volume);
17 if (result.IsSuccess()) {
18 // TODO: SendVibrationInBool
19 }
20 }
21
22 ref_counter++;
23 return ResultSuccess;
24}
25
26Result NpadN64VibrationDevice::DecrementRefCounter() {
27 if (ref_counter == 1) {
28 if (!is_mounted) {
29 ref_counter = 0;
30 if (is_mounted != false) {
31 // TODO: SendVibrationInBool
32 }
33 return ResultSuccess;
34 }
35 f32 volume = 1.0f;
36 const auto result = vibration_handler->GetVibrationVolume(volume);
37 if (result.IsSuccess()) {
38 // TODO
39 }
40 }
41
42 if (ref_counter > 0) {
43 ref_counter--;
44 }
45
46 return ResultSuccess;
47}
48
49Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) {
50 if (ref_counter < 1) {
51 return ResultVibrationNotInitialized;
52 }
53 if (is_mounted) {
54 f32 volume = 1.0f;
55 const auto result = vibration_handler->GetVibrationVolume(volume);
56 if (result.IsError()) {
57 return result;
58 }
59 // TODO: SendVibrationInBool
60 }
61 return ResultSuccess;
62}
63
64Result NpadN64VibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u32 pattern) {
65 if (!is_mounted) {
66 return ResultSuccess;
67 }
68 f32 volume = 1.0f;
69 const auto result = vibration_handler->GetVibrationVolume(volume);
70 if (result.IsError()) {
71 return result;
72 }
73 if (volume <= 0.0) {
74 pattern = 0;
75 }
76 // TODO: SendVibrationNotificationPattern
77 return ResultSuccess;
78}
79
80} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.h b/src/hid_core/resources/vibration/n64_vibration_device.h
new file mode 100644
index 000000000..54e6efc1a
--- /dev/null
+++ b/src/hid_core/resources/vibration/n64_vibration_device.h
@@ -0,0 +1,29 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <mutex>
8
9#include "common/common_types.h"
10#include "core/hle/result.h"
11#include "hid_core/hid_types.h"
12#include "hid_core/resources/npad/npad_types.h"
13#include "hid_core/resources/vibration/vibration_base.h"
14
15namespace Service::HID {
16class NpadVibration;
17
18/// Handles Npad request from HID interfaces
19class NpadN64VibrationDevice final : public NpadVibrationBase {
20public:
21 explicit NpadN64VibrationDevice();
22
23 Result IncrementRefCounter() override;
24 Result DecrementRefCounter() override;
25
26 Result SendValueInBool(bool is_vibrating);
27 Result SendVibrationNotificationPattern(u32 pattern);
28};
29} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/vibration_base.cpp b/src/hid_core/resources/vibration/vibration_base.cpp
new file mode 100644
index 000000000..350f349c2
--- /dev/null
+++ b/src/hid_core/resources/vibration/vibration_base.cpp
@@ -0,0 +1,30 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h"
7#include "hid_core/resources/vibration/vibration_base.h"
8
9namespace Service::HID {
10
11NpadVibrationBase::NpadVibrationBase() {}
12
13Result NpadVibrationBase::IncrementRefCounter() {
14 ref_counter++;
15 return ResultSuccess;
16}
17
18Result NpadVibrationBase::DecrementRefCounter() {
19 if (ref_counter > 0) {
20 ref_counter--;
21 }
22
23 return ResultSuccess;
24}
25
26bool NpadVibrationBase::IsVibrationMounted() const {
27 return is_mounted;
28}
29
30} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/vibration_base.h b/src/hid_core/resources/vibration/vibration_base.h
new file mode 100644
index 000000000..c6c5fc4d9
--- /dev/null
+++ b/src/hid_core/resources/vibration/vibration_base.h
@@ -0,0 +1,28 @@
1// SPDX-FileCopyrightText: Copyright 2024 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/hle/result.h"
8
9namespace Service::HID {
10class NpadVibration;
11
12/// Handles Npad request from HID interfaces
13class NpadVibrationBase {
14public:
15 explicit NpadVibrationBase();
16
17 virtual Result IncrementRefCounter();
18 virtual Result DecrementRefCounter();
19
20 bool IsVibrationMounted() const;
21
22protected:
23 u64 xcd_handle{};
24 s32 ref_counter{};
25 bool is_mounted{};
26 NpadVibration* vibration_handler{nullptr};
27};
28} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/vibration_device.cpp b/src/hid_core/resources/vibration/vibration_device.cpp
new file mode 100644
index 000000000..888c3a7ed
--- /dev/null
+++ b/src/hid_core/resources/vibration/vibration_device.cpp
@@ -0,0 +1,84 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h"
7#include "hid_core/resources/vibration/vibration_device.h"
8
9namespace Service::HID {
10
11NpadVibrationDevice::NpadVibrationDevice() {}
12
13Result NpadVibrationDevice::IncrementRefCounter() {
14 ref_counter++;
15 return ResultSuccess;
16}
17
18Result NpadVibrationDevice::DecrementRefCounter() {
19 if (ref_counter > 0) {
20 ref_counter--;
21 }
22
23 return ResultSuccess;
24}
25
26Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) {
27 if (ref_counter == 0) {
28 return ResultVibrationNotInitialized;
29 }
30 if (!is_mounted) {
31 return ResultSuccess;
32 }
33
34 f32 volume = 1.0f;
35 const auto result = vibration_handler->GetVibrationVolume(volume);
36 if (result.IsError()) {
37 return result;
38 }
39 if (volume <= 0.0f) {
40 // TODO: SendVibrationValue
41 return ResultSuccess;
42 }
43
44 Core::HID::VibrationValue vibration_value = value;
45 vibration_value.high_amplitude *= volume;
46 vibration_value.low_amplitude *= volume;
47
48 // TODO: SendVibrationValue
49 return ResultSuccess;
50}
51
52Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u32 pattern) {
53 if (!is_mounted) {
54 return ResultSuccess;
55 }
56
57 f32 volume = 1.0f;
58 const auto result = vibration_handler->GetVibrationVolume(volume);
59 if (result.IsError()) {
60 return result;
61 }
62 if (volume <= 0.0) {
63 pattern = 0;
64 }
65
66 // return xcd_handle->SendVibrationNotificationPattern(pattern);
67 return ResultSuccess;
68}
69
70Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) {
71 if (ref_counter < 1) {
72 return ResultVibrationNotInitialized;
73 }
74
75 out_value = Core::HID::DEFAULT_VIBRATION_VALUE;
76 if (!is_mounted) {
77 return ResultSuccess;
78 }
79
80 // TODO: SendVibrationValue
81 return ResultSuccess;
82}
83
84} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/vibration_device.h b/src/hid_core/resources/vibration/vibration_device.h
new file mode 100644
index 000000000..3574ad60b
--- /dev/null
+++ b/src/hid_core/resources/vibration/vibration_device.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <array>
7#include <mutex>
8
9#include "common/common_types.h"
10#include "core/hle/result.h"
11#include "hid_core/hid_types.h"
12#include "hid_core/resources/npad/npad_types.h"
13#include "hid_core/resources/vibration/vibration_base.h"
14
15namespace Service::HID {
16class NpadVibration;
17
18/// Handles Npad request from HID interfaces
19class NpadVibrationDevice final : public NpadVibrationBase {
20public:
21 explicit NpadVibrationDevice();
22
23 Result IncrementRefCounter();
24 Result DecrementRefCounter();
25
26 Result SendVibrationValue(const Core::HID::VibrationValue& value);
27 Result SendVibrationNotificationPattern(u32 pattern);
28
29 Result GetActualVibrationValue(Core::HID::VibrationValue& out_value);
30
31private:
32 u32 device_index{};
33};
34
35} // namespace Service::HID