diff options
Diffstat (limited to 'src/core/hle')
95 files changed, 60 insertions, 9717 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 97eb56ff0..9e05bdafa 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/registered_cache.h" | 14 | #include "core/file_sys/registered_cache.h" |
| 15 | #include "core/file_sys/savedata_factory.h" | 15 | #include "core/file_sys/savedata_factory.h" |
| 16 | #include "core/hid/hid_types.h" | ||
| 17 | #include "core/hle/kernel/k_event.h" | 16 | #include "core/hle/kernel/k_event.h" |
| 18 | #include "core/hle/kernel/k_transfer_memory.h" | 17 | #include "core/hle/kernel/k_transfer_memory.h" |
| 19 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| @@ -37,7 +36,6 @@ | |||
| 37 | #include "core/hle/service/caps/caps_su.h" | 36 | #include "core/hle/service/caps/caps_su.h" |
| 38 | #include "core/hle/service/caps/caps_types.h" | 37 | #include "core/hle/service/caps/caps_types.h" |
| 39 | #include "core/hle/service/filesystem/filesystem.h" | 38 | #include "core/hle/service/filesystem/filesystem.h" |
| 40 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 41 | #include "core/hle/service/ipc_helpers.h" | 39 | #include "core/hle/service/ipc_helpers.h" |
| 42 | #include "core/hle/service/ns/ns.h" | 40 | #include "core/hle/service/ns/ns.h" |
| 43 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | 41 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" |
| @@ -48,6 +46,8 @@ | |||
| 48 | #include "core/hle/service/vi/vi.h" | 46 | #include "core/hle/service/vi/vi.h" |
| 49 | #include "core/hle/service/vi/vi_results.h" | 47 | #include "core/hle/service/vi/vi_results.h" |
| 50 | #include "core/memory.h" | 48 | #include "core/memory.h" |
| 49 | #include "hid_core/hid_types.h" | ||
| 50 | #include "hid_core/resources/npad/npad.h" | ||
| 51 | 51 | ||
| 52 | namespace Service::AM { | 52 | namespace Service::AM { |
| 53 | 53 | ||
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 3906c0fa4..c2ff444a6 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp | |||
| @@ -5,13 +5,13 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/frontend/applets/cabinet.h" | 7 | #include "core/frontend/applets/cabinet.h" |
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 11 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/applet_cabinet.h" | 11 | #include "core/hle/service/am/applets/applet_cabinet.h" |
| 13 | #include "core/hle/service/mii/mii_manager.h" | 12 | #include "core/hle/service/mii/mii_manager.h" |
| 14 | #include "core/hle/service/nfc/common/device.h" | 13 | #include "core/hle/service/nfc/common/device.h" |
| 14 | #include "hid_core/hid_core.h" | ||
| 15 | 15 | ||
| 16 | namespace Service::AM::Applets { | 16 | namespace Service::AM::Applets { |
| 17 | 17 | ||
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 9840d2547..0e4d9cc39 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp | |||
| @@ -9,13 +9,13 @@ | |||
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/frontend/applets/controller.h" | 11 | #include "core/frontend/applets/controller.h" |
| 12 | #include "core/hid/emulated_controller.h" | ||
| 13 | #include "core/hid/hid_core.h" | ||
| 14 | #include "core/hid/hid_types.h" | ||
| 15 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 16 | #include "core/hle/service/am/am.h" | 13 | #include "core/hle/service/am/am.h" |
| 17 | #include "core/hle/service/am/applets/applet_controller.h" | 14 | #include "core/hle/service/am/applets/applet_controller.h" |
| 18 | #include "core/hle/service/hid/controllers/npad.h" | 15 | #include "hid_core/frontend/emulated_controller.h" |
| 16 | #include "hid_core/hid_core.h" | ||
| 17 | #include "hid_core/hid_types.h" | ||
| 18 | #include "hid_core/resources/npad/npad.h" | ||
| 19 | 19 | ||
| 20 | namespace Service::AM::Applets { | 20 | namespace Service::AM::Applets { |
| 21 | 21 | ||
diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp deleted file mode 100644 index b4ff663c2..000000000 --- a/src/core/hle/service/hid/controllers/applet_resource.cpp +++ /dev/null | |||
| @@ -1,329 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 6 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | #include "core/hle/service/hid/errors.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | AppletResource::AppletResource(Core::System& system_) : system{system_} {} | ||
| 13 | |||
| 14 | AppletResource::~AppletResource() = default; | ||
| 15 | |||
| 16 | Result AppletResource::CreateAppletResource(u64 aruid) { | ||
| 17 | const u64 index = GetIndexFromAruid(aruid); | ||
| 18 | |||
| 19 | if (index >= AruidIndexMax) { | ||
| 20 | return ResultAruidNotRegistered; | ||
| 21 | } | ||
| 22 | |||
| 23 | if (data[index].flag.is_assigned) { | ||
| 24 | return ResultAruidAlreadyRegistered; | ||
| 25 | } | ||
| 26 | |||
| 27 | auto& shared_memory = shared_memory_holder[index]; | ||
| 28 | if (!shared_memory.IsMapped()) { | ||
| 29 | const Result result = shared_memory.Initialize(system); | ||
| 30 | if (result.IsError()) { | ||
| 31 | return result; | ||
| 32 | } | ||
| 33 | if (shared_memory.GetAddress() == nullptr) { | ||
| 34 | shared_memory.Finalize(); | ||
| 35 | return ResultSharedMemoryNotInitialized; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | auto* shared_memory_format = shared_memory.GetAddress(); | ||
| 40 | if (shared_memory_format != nullptr) { | ||
| 41 | shared_memory_format->Initialize(); | ||
| 42 | } | ||
| 43 | |||
| 44 | data[index].shared_memory_format = shared_memory_format; | ||
| 45 | data[index].flag.is_assigned.Assign(true); | ||
| 46 | // TODO: InitializeSixAxisControllerConfig(false); | ||
| 47 | active_aruid = aruid; | ||
| 48 | return ResultSuccess; | ||
| 49 | } | ||
| 50 | |||
| 51 | Result AppletResource::RegisterAppletResourceUserId(u64 aruid, bool enable_input) { | ||
| 52 | const u64 index = GetIndexFromAruid(aruid); | ||
| 53 | |||
| 54 | if (index < AruidIndexMax) { | ||
| 55 | return ResultAruidAlreadyRegistered; | ||
| 56 | } | ||
| 57 | |||
| 58 | std::size_t data_index = AruidIndexMax; | ||
| 59 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 60 | if (!data[i].flag.is_initialized) { | ||
| 61 | data_index = i; | ||
| 62 | break; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | if (data_index == AruidIndexMax) { | ||
| 67 | return ResultAruidNoAvailableEntries; | ||
| 68 | } | ||
| 69 | |||
| 70 | AruidData& aruid_data = data[data_index]; | ||
| 71 | |||
| 72 | aruid_data.aruid = aruid; | ||
| 73 | aruid_data.flag.is_initialized.Assign(true); | ||
| 74 | if (enable_input) { | ||
| 75 | aruid_data.flag.enable_pad_input.Assign(true); | ||
| 76 | aruid_data.flag.enable_six_axis_sensor.Assign(true); | ||
| 77 | aruid_data.flag.bit_18.Assign(true); | ||
| 78 | aruid_data.flag.enable_touchscreen.Assign(true); | ||
| 79 | } | ||
| 80 | |||
| 81 | data_index = AruidIndexMax; | ||
| 82 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 83 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 84 | if (registration_list.aruid[i] != aruid) { | ||
| 85 | continue; | ||
| 86 | } | ||
| 87 | data_index = i; | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | if (registration_list.flag[i] == RegistrationStatus::None) { | ||
| 91 | data_index = i; | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | if (data_index == AruidIndexMax) { | ||
| 97 | return ResultSuccess; | ||
| 98 | } | ||
| 99 | |||
| 100 | registration_list.flag[data_index] = RegistrationStatus::Initialized; | ||
| 101 | registration_list.aruid[data_index] = aruid; | ||
| 102 | |||
| 103 | return ResultSuccess; | ||
| 104 | } | ||
| 105 | |||
| 106 | void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 107 | u64 index = GetIndexFromAruid(aruid); | ||
| 108 | |||
| 109 | if (index < AruidIndexMax) { | ||
| 110 | if (data[index].flag.is_assigned) { | ||
| 111 | data[index].shared_memory_format = nullptr; | ||
| 112 | data[index].flag.is_assigned.Assign(false); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | index = GetIndexFromAruid(aruid); | ||
| 117 | if (index < AruidIndexMax) { | ||
| 118 | DestroySevenSixAxisTransferMemory(); | ||
| 119 | data[index].flag.raw = 0; | ||
| 120 | data[index].aruid = 0; | ||
| 121 | |||
| 122 | index = GetIndexFromAruid(aruid); | ||
| 123 | if (index < AruidIndexMax) { | ||
| 124 | registration_list.flag[index] = RegistrationStatus::PendingDelete; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | void AppletResource::FreeAppletResourceId(u64 aruid) { | ||
| 130 | u64 index = GetIndexFromAruid(aruid); | ||
| 131 | if (index >= AruidIndexMax) { | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | |||
| 135 | auto& aruid_data = data[index]; | ||
| 136 | if (aruid_data.flag.is_assigned) { | ||
| 137 | aruid_data.shared_memory_format = nullptr; | ||
| 138 | aruid_data.flag.is_assigned.Assign(false); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | u64 AppletResource::GetActiveAruid() { | ||
| 143 | return active_aruid; | ||
| 144 | } | ||
| 145 | |||
| 146 | Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { | ||
| 147 | u64 index = GetIndexFromAruid(aruid); | ||
| 148 | if (index >= AruidIndexMax) { | ||
| 149 | return ResultAruidNotRegistered; | ||
| 150 | } | ||
| 151 | |||
| 152 | *out_handle = shared_memory_holder[index].GetHandle(); | ||
| 153 | return ResultSuccess; | ||
| 154 | } | ||
| 155 | |||
| 156 | Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, | ||
| 157 | u64 aruid) { | ||
| 158 | u64 index = GetIndexFromAruid(aruid); | ||
| 159 | if (index >= AruidIndexMax) { | ||
| 160 | return ResultAruidNotRegistered; | ||
| 161 | } | ||
| 162 | |||
| 163 | *out_shared_memory_format = data[index].shared_memory_format; | ||
| 164 | return ResultSuccess; | ||
| 165 | } | ||
| 166 | |||
| 167 | AruidData* AppletResource::GetAruidData(u64 aruid) { | ||
| 168 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 169 | if (aruid_index == AruidIndexMax) { | ||
| 170 | return nullptr; | ||
| 171 | } | ||
| 172 | return &data[aruid_index]; | ||
| 173 | } | ||
| 174 | |||
| 175 | AruidData* AppletResource::GetAruidDataByIndex(std::size_t aruid_index) { | ||
| 176 | return &data[aruid_index]; | ||
| 177 | } | ||
| 178 | |||
| 179 | bool AppletResource::IsVibrationAruidActive(u64 aruid) const { | ||
| 180 | return aruid == 0 || aruid == active_vibration_aruid; | ||
| 181 | } | ||
| 182 | |||
| 183 | u64 AppletResource::GetIndexFromAruid(u64 aruid) { | ||
| 184 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 185 | if (registration_list.flag[i] == RegistrationStatus::Initialized && | ||
| 186 | registration_list.aruid[i] == aruid) { | ||
| 187 | return i; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | return AruidIndexMax; | ||
| 191 | } | ||
| 192 | |||
| 193 | Result AppletResource::DestroySevenSixAxisTransferMemory() { | ||
| 194 | // TODO | ||
| 195 | return ResultSuccess; | ||
| 196 | } | ||
| 197 | |||
| 198 | void AppletResource::EnableInput(u64 aruid, bool is_enabled) { | ||
| 199 | const u64 index = GetIndexFromAruid(aruid); | ||
| 200 | if (index >= AruidIndexMax) { | ||
| 201 | return; | ||
| 202 | } | ||
| 203 | |||
| 204 | data[index].flag.enable_pad_input.Assign(is_enabled); | ||
| 205 | data[index].flag.enable_touchscreen.Assign(is_enabled); | ||
| 206 | } | ||
| 207 | |||
| 208 | void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { | ||
| 209 | const u64 index = GetIndexFromAruid(aruid); | ||
| 210 | if (index >= AruidIndexMax) { | ||
| 211 | return; | ||
| 212 | } | ||
| 213 | |||
| 214 | data[index].flag.enable_six_axis_sensor.Assign(is_enabled); | ||
| 215 | } | ||
| 216 | |||
| 217 | void AppletResource::EnablePadInput(u64 aruid, bool is_enabled) { | ||
| 218 | const u64 index = GetIndexFromAruid(aruid); | ||
| 219 | if (index >= AruidIndexMax) { | ||
| 220 | return; | ||
| 221 | } | ||
| 222 | |||
| 223 | data[index].flag.enable_pad_input.Assign(is_enabled); | ||
| 224 | } | ||
| 225 | |||
| 226 | void AppletResource::EnableTouchScreen(u64 aruid, bool is_enabled) { | ||
| 227 | const u64 index = GetIndexFromAruid(aruid); | ||
| 228 | if (index >= AruidIndexMax) { | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | |||
| 232 | data[index].flag.enable_touchscreen.Assign(is_enabled); | ||
| 233 | } | ||
| 234 | |||
| 235 | void AppletResource::SetIsPalmaConnectable(u64 aruid, bool is_connectable) { | ||
| 236 | const u64 index = GetIndexFromAruid(aruid); | ||
| 237 | if (index >= AruidIndexMax) { | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | |||
| 241 | data[index].flag.is_palma_connectable.Assign(is_connectable); | ||
| 242 | } | ||
| 243 | |||
| 244 | void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) { | ||
| 245 | const u64 index = GetIndexFromAruid(aruid); | ||
| 246 | if (index >= AruidIndexMax) { | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | |||
| 250 | data[index].flag.enable_palma_boost_mode.Assign(is_enabled); | ||
| 251 | } | ||
| 252 | |||
| 253 | Result AppletResource::RegisterCoreAppletResource() { | ||
| 254 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 255 | return ResultAppletResourceOverflow; | ||
| 256 | } | ||
| 257 | if (ref_counter == 0) { | ||
| 258 | const u64 index = GetIndexFromAruid(0); | ||
| 259 | if (index < AruidIndexMax) { | ||
| 260 | return ResultAruidAlreadyRegistered; | ||
| 261 | } | ||
| 262 | |||
| 263 | std::size_t data_index = AruidIndexMax; | ||
| 264 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 265 | if (!data[i].flag.is_initialized) { | ||
| 266 | data_index = i; | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | if (data_index == AruidIndexMax) { | ||
| 272 | return ResultAruidNoAvailableEntries; | ||
| 273 | } | ||
| 274 | |||
| 275 | AruidData& aruid_data = data[data_index]; | ||
| 276 | |||
| 277 | aruid_data.aruid = 0; | ||
| 278 | aruid_data.flag.is_initialized.Assign(true); | ||
| 279 | aruid_data.flag.enable_pad_input.Assign(true); | ||
| 280 | aruid_data.flag.enable_six_axis_sensor.Assign(true); | ||
| 281 | aruid_data.flag.bit_18.Assign(true); | ||
| 282 | aruid_data.flag.enable_touchscreen.Assign(true); | ||
| 283 | |||
| 284 | data_index = AruidIndexMax; | ||
| 285 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 286 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 287 | if (registration_list.aruid[i] != 0) { | ||
| 288 | continue; | ||
| 289 | } | ||
| 290 | data_index = i; | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | if (registration_list.flag[i] == RegistrationStatus::None) { | ||
| 294 | data_index = i; | ||
| 295 | break; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | Result result = ResultSuccess; | ||
| 300 | |||
| 301 | if (data_index == AruidIndexMax) { | ||
| 302 | result = CreateAppletResource(0); | ||
| 303 | } else { | ||
| 304 | registration_list.flag[data_index] = RegistrationStatus::Initialized; | ||
| 305 | registration_list.aruid[data_index] = 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (result.IsError()) { | ||
| 309 | UnregisterAppletResourceUserId(0); | ||
| 310 | return result; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | ref_counter++; | ||
| 314 | return ResultSuccess; | ||
| 315 | } | ||
| 316 | |||
| 317 | Result AppletResource::UnregisterCoreAppletResource() { | ||
| 318 | if (ref_counter == 0) { | ||
| 319 | return ResultAppletResourceNotInitialized; | ||
| 320 | } | ||
| 321 | |||
| 322 | if (--ref_counter == 0) { | ||
| 323 | UnregisterAppletResourceUserId(0); | ||
| 324 | } | ||
| 325 | |||
| 326 | return ResultSuccess; | ||
| 327 | } | ||
| 328 | |||
| 329 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h deleted file mode 100644 index 0862fdc2f..000000000 --- a/src/core/hle/service/hid/controllers/applet_resource.h +++ /dev/null | |||
| @@ -1,123 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 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/bit_field.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | #include "core/hle/service/hid/controllers/shared_memory_holder.h" | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Kernel { | ||
| 19 | class KSharedMemory; | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace Service::HID { | ||
| 23 | struct SharedMemoryFormat; | ||
| 24 | class AppletResource; | ||
| 25 | class NPadResource; | ||
| 26 | |||
| 27 | static constexpr std::size_t AruidIndexMax = 0x20; | ||
| 28 | static constexpr u64 SystemAruid = 0; | ||
| 29 | |||
| 30 | enum class RegistrationStatus : u32 { | ||
| 31 | None, | ||
| 32 | Initialized, | ||
| 33 | PendingDelete, | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct DataStatusFlag { | ||
| 37 | union { | ||
| 38 | u32 raw{}; | ||
| 39 | |||
| 40 | BitField<0, 1, u32> is_initialized; | ||
| 41 | BitField<1, 1, u32> is_assigned; | ||
| 42 | BitField<16, 1, u32> enable_pad_input; | ||
| 43 | BitField<17, 1, u32> enable_six_axis_sensor; | ||
| 44 | BitField<18, 1, u32> bit_18; | ||
| 45 | BitField<19, 1, u32> is_palma_connectable; | ||
| 46 | BitField<20, 1, u32> enable_palma_boost_mode; | ||
| 47 | BitField<21, 1, u32> enable_touchscreen; | ||
| 48 | }; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct AruidRegisterList { | ||
| 52 | std::array<RegistrationStatus, AruidIndexMax> flag{}; | ||
| 53 | std::array<u64, AruidIndexMax> aruid{}; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(AruidRegisterList) == 0x180, "AruidRegisterList is an invalid size"); | ||
| 56 | |||
| 57 | struct AruidData { | ||
| 58 | DataStatusFlag flag{}; | ||
| 59 | u64 aruid{}; | ||
| 60 | SharedMemoryFormat* shared_memory_format{nullptr}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct HandheldConfig { | ||
| 64 | bool is_handheld_hid_enabled; | ||
| 65 | bool is_force_handheld; | ||
| 66 | bool is_joycon_rail_enabled; | ||
| 67 | bool is_force_handheld_style_vibration; | ||
| 68 | }; | ||
| 69 | static_assert(sizeof(HandheldConfig) == 0x4, "HandheldConfig is an invalid size"); | ||
| 70 | |||
| 71 | struct AppletResourceHolder { | ||
| 72 | std::shared_ptr<AppletResource> applet_resource{nullptr}; | ||
| 73 | std::recursive_mutex* shared_mutex{nullptr}; | ||
| 74 | NPadResource* shared_npad_resource{nullptr}; | ||
| 75 | std::shared_ptr<HandheldConfig> handheld_config{nullptr}; | ||
| 76 | long* handle_1; | ||
| 77 | }; | ||
| 78 | |||
| 79 | class AppletResource { | ||
| 80 | public: | ||
| 81 | explicit AppletResource(Core::System& system_); | ||
| 82 | ~AppletResource(); | ||
| 83 | |||
| 84 | Result CreateAppletResource(u64 aruid); | ||
| 85 | |||
| 86 | Result RegisterAppletResourceUserId(u64 aruid, bool enable_input); | ||
| 87 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 88 | |||
| 89 | void FreeAppletResourceId(u64 aruid); | ||
| 90 | |||
| 91 | u64 GetActiveAruid(); | ||
| 92 | Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); | ||
| 93 | Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid); | ||
| 94 | AruidData* GetAruidData(u64 aruid); | ||
| 95 | AruidData* GetAruidDataByIndex(std::size_t aruid_index); | ||
| 96 | |||
| 97 | bool IsVibrationAruidActive(u64 aruid) const; | ||
| 98 | |||
| 99 | u64 GetIndexFromAruid(u64 aruid); | ||
| 100 | |||
| 101 | Result DestroySevenSixAxisTransferMemory(); | ||
| 102 | |||
| 103 | void EnableInput(u64 aruid, bool is_enabled); | ||
| 104 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); | ||
| 105 | void EnablePadInput(u64 aruid, bool is_enabled); | ||
| 106 | void EnableTouchScreen(u64 aruid, bool is_enabled); | ||
| 107 | void SetIsPalmaConnectable(u64 aruid, bool is_connectable); | ||
| 108 | void EnablePalmaBoostMode(u64 aruid, bool is_enabled); | ||
| 109 | |||
| 110 | Result RegisterCoreAppletResource(); | ||
| 111 | Result UnregisterCoreAppletResource(); | ||
| 112 | |||
| 113 | private: | ||
| 114 | u64 active_aruid{}; | ||
| 115 | AruidRegisterList registration_list{}; | ||
| 116 | std::array<AruidData, AruidIndexMax> data{}; | ||
| 117 | std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{}; | ||
| 118 | s32 ref_counter{}; | ||
| 119 | u64 active_vibration_aruid; | ||
| 120 | |||
| 121 | Core::System& system; | ||
| 122 | }; | ||
| 123 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/capture_button.cpp b/src/core/hle/service/hid/controllers/capture_button.cpp deleted file mode 100644 index 7847c080e..000000000 --- a/src/core/hle/service/hid/controllers/capture_button.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/capture_button.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | CaptureButton::CaptureButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | CaptureButton::~CaptureButton() = default; | ||
| 14 | |||
| 15 | void CaptureButton::OnInit() {} | ||
| 16 | |||
| 17 | void CaptureButton::OnRelease() {} | ||
| 18 | |||
| 19 | void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->capture_button.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/capture_button.h b/src/core/hle/service/hid/controllers/capture_button.h deleted file mode 100644 index dcc4715c5..000000000 --- a/src/core/hle/service/hid/controllers/capture_button.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class CaptureButton final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit CaptureButton(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~CaptureButton() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp deleted file mode 100644 index 4b574c2e5..000000000 --- a/src/core/hle/service/hid/controllers/console_six_axis.cpp +++ /dev/null | |||
| @@ -1,45 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hid/emulated_console.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hle/service/hid/controllers/console_six_axis.h" | ||
| 8 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 13 | console = hid_core.GetEmulatedConsole(); | ||
| 14 | } | ||
| 15 | |||
| 16 | ConsoleSixAxis::~ConsoleSixAxis() = default; | ||
| 17 | |||
| 18 | void ConsoleSixAxis::OnInit() {} | ||
| 19 | |||
| 20 | void ConsoleSixAxis::OnRelease() {} | ||
| 21 | |||
| 22 | void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 23 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 24 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 25 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 26 | |||
| 27 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | ConsoleSixAxisSensorSharedMemoryFormat& shared_memory = data->shared_memory_format->console; | ||
| 32 | |||
| 33 | if (!IsControllerActivated()) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | const auto motion_status = console->GetMotion(); | ||
| 38 | |||
| 39 | shared_memory.sampling_number++; | ||
| 40 | shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; | ||
| 41 | shared_memory.verticalization_error = motion_status.verticalization_error; | ||
| 42 | shared_memory.gyro_bias = motion_status.gyro_bias; | ||
| 43 | } | ||
| 44 | |||
| 45 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h deleted file mode 100644 index e3351f83c..000000000 --- a/src/core/hle/service/hid/controllers/console_six_axis.h +++ /dev/null | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | class EmulatedConsole; | ||
| 10 | } // namespace Core::HID | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | class ConsoleSixAxis final : public ControllerBase { | ||
| 14 | public: | ||
| 15 | explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_); | ||
| 16 | ~ConsoleSixAxis() override; | ||
| 17 | |||
| 18 | // Called when the controller is initialized | ||
| 19 | void OnInit() override; | ||
| 20 | |||
| 21 | // When the controller is released | ||
| 22 | void OnRelease() override; | ||
| 23 | |||
| 24 | // When the controller is requesting an update for the shared memory | ||
| 25 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 26 | |||
| 27 | private: | ||
| 28 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 29 | }; | ||
| 30 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp deleted file mode 100644 index afca7154c..000000000 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | |||
| 8 | ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} | ||
| 9 | ControllerBase::~ControllerBase() = default; | ||
| 10 | |||
| 11 | Result ControllerBase::Activate() { | ||
| 12 | if (is_activated) { | ||
| 13 | return ResultSuccess; | ||
| 14 | } | ||
| 15 | is_activated = true; | ||
| 16 | OnInit(); | ||
| 17 | return ResultSuccess; | ||
| 18 | } | ||
| 19 | |||
| 20 | Result ControllerBase::Activate(u64 aruid) { | ||
| 21 | return Activate(); | ||
| 22 | } | ||
| 23 | |||
| 24 | void ControllerBase::DeactivateController() { | ||
| 25 | if (is_activated) { | ||
| 26 | OnRelease(); | ||
| 27 | } | ||
| 28 | is_activated = false; | ||
| 29 | } | ||
| 30 | |||
| 31 | bool ControllerBase::IsControllerActivated() const { | ||
| 32 | return is_activated; | ||
| 33 | } | ||
| 34 | |||
| 35 | void ControllerBase::SetAppletResource(std::shared_ptr<AppletResource> resource, | ||
| 36 | std::recursive_mutex* resource_mutex) { | ||
| 37 | applet_resource = resource; | ||
| 38 | shared_mutex = resource_mutex; | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h deleted file mode 100644 index b34b85ece..000000000 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 11 | |||
| 12 | namespace Core::Timing { | ||
| 13 | class CoreTiming; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Core::HID { | ||
| 17 | class HIDCore; | ||
| 18 | } // namespace Core::HID | ||
| 19 | |||
| 20 | namespace Service::HID { | ||
| 21 | class ControllerBase { | ||
| 22 | public: | ||
| 23 | explicit ControllerBase(Core::HID::HIDCore& hid_core_); | ||
| 24 | virtual ~ControllerBase(); | ||
| 25 | |||
| 26 | // Called when the controller is initialized | ||
| 27 | virtual void OnInit() = 0; | ||
| 28 | |||
| 29 | // When the controller is released | ||
| 30 | virtual void OnRelease() = 0; | ||
| 31 | |||
| 32 | // When the controller is requesting an update for the shared memory | ||
| 33 | virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing) = 0; | ||
| 34 | |||
| 35 | // When the controller is requesting a motion update for the shared memory | ||
| 36 | virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} | ||
| 37 | |||
| 38 | Result Activate(); | ||
| 39 | Result Activate(u64 aruid); | ||
| 40 | |||
| 41 | void DeactivateController(); | ||
| 42 | |||
| 43 | bool IsControllerActivated() const; | ||
| 44 | |||
| 45 | void SetAppletResource(std::shared_ptr<AppletResource> resource, | ||
| 46 | std::recursive_mutex* resource_mutex); | ||
| 47 | |||
| 48 | protected: | ||
| 49 | bool is_activated{false}; | ||
| 50 | std::shared_ptr<AppletResource> applet_resource{nullptr}; | ||
| 51 | std::recursive_mutex* shared_mutex{nullptr}; | ||
| 52 | |||
| 53 | Core::HID::HIDCore& hid_core; | ||
| 54 | }; | ||
| 55 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_mouse.cpp b/src/core/hle/service/hid/controllers/debug_mouse.cpp deleted file mode 100644 index ceeb78d36..000000000 --- a/src/core/hle/service/hid/controllers/debug_mouse.cpp +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/frontend/emu_window.h" | ||
| 6 | #include "core/hid/emulated_devices.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 9 | #include "core/hle/service/hid/controllers/debug_mouse.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | DebugMouse::DebugMouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 15 | emulated_devices = hid_core.GetEmulatedDevices(); | ||
| 16 | } | ||
| 17 | |||
| 18 | DebugMouse::~DebugMouse() = default; | ||
| 19 | |||
| 20 | void DebugMouse::OnInit() {} | ||
| 21 | void DebugMouse::OnRelease() {} | ||
| 22 | |||
| 23 | void DebugMouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | MouseSharedMemoryFormat& shared_memory = data->shared_memory_format->debug_mouse; | ||
| 33 | |||
| 34 | if (!IsControllerActivated()) { | ||
| 35 | shared_memory.mouse_lifo.buffer_count = 0; | ||
| 36 | shared_memory.mouse_lifo.buffer_tail = 0; | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | |||
| 40 | next_state = {}; | ||
| 41 | |||
| 42 | const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; | ||
| 43 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 44 | |||
| 45 | if (Settings::values.mouse_enabled) { | ||
| 46 | const auto& mouse_button_state = emulated_devices->GetMouseButtons(); | ||
| 47 | const auto& mouse_position_state = emulated_devices->GetMousePosition(); | ||
| 48 | const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); | ||
| 49 | next_state.attribute.is_connected.Assign(1); | ||
| 50 | next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); | ||
| 51 | next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); | ||
| 52 | next_state.delta_x = next_state.x - last_entry.x; | ||
| 53 | next_state.delta_y = next_state.y - last_entry.y; | ||
| 54 | next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; | ||
| 55 | next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; | ||
| 56 | |||
| 57 | last_mouse_wheel_state = mouse_wheel_state; | ||
| 58 | next_state.button = mouse_button_state; | ||
| 59 | } | ||
| 60 | |||
| 61 | shared_memory.mouse_lifo.WriteNextEntry(next_state); | ||
| 62 | } | ||
| 63 | |||
| 64 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_mouse.h b/src/core/hle/service/hid/controllers/debug_mouse.h deleted file mode 100644 index ec939fa9f..000000000 --- a/src/core/hle/service/hid/controllers/debug_mouse.h +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | class EmulatedDevices; | ||
| 10 | struct MouseState; | ||
| 11 | struct AnalogStickState; | ||
| 12 | } // namespace Core::HID | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | class DebugMouse final : public ControllerBase { | ||
| 16 | public: | ||
| 17 | explicit DebugMouse(Core::HID::HIDCore& hid_core_); | ||
| 18 | ~DebugMouse() override; | ||
| 19 | |||
| 20 | // Called when the controller is initialized | ||
| 21 | void OnInit() override; | ||
| 22 | |||
| 23 | // When the controller is released | ||
| 24 | void OnRelease() override; | ||
| 25 | |||
| 26 | // When the controller is requesting an update for the shared memory | ||
| 27 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 28 | |||
| 29 | private: | ||
| 30 | Core::HID::MouseState next_state{}; | ||
| 31 | Core::HID::AnalogStickState last_mouse_wheel_state{}; | ||
| 32 | Core::HID::EmulatedDevices* emulated_devices = nullptr; | ||
| 33 | }; | ||
| 34 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp deleted file mode 100644 index dc83f90f3..000000000 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 10 | #include "core/hle/service/hid/controllers/debug_pad.h" | ||
| 11 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | DebugPad::DebugPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 16 | controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); | ||
| 17 | } | ||
| 18 | |||
| 19 | DebugPad::~DebugPad() = default; | ||
| 20 | |||
| 21 | void DebugPad::OnInit() {} | ||
| 22 | |||
| 23 | void DebugPad::OnRelease() {} | ||
| 24 | |||
| 25 | void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 26 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 27 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 28 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 29 | |||
| 30 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | |||
| 34 | DebugPadSharedMemoryFormat& shared_memory = data->shared_memory_format->debug_pad; | ||
| 35 | |||
| 36 | if (!IsControllerActivated()) { | ||
| 37 | shared_memory.debug_pad_lifo.buffer_count = 0; | ||
| 38 | shared_memory.debug_pad_lifo.buffer_tail = 0; | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state; | ||
| 43 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 44 | |||
| 45 | if (Settings::values.debug_pad_enabled) { | ||
| 46 | next_state.attribute.connected.Assign(1); | ||
| 47 | |||
| 48 | const auto& button_state = controller->GetDebugPadButtons(); | ||
| 49 | const auto& stick_state = controller->GetSticks(); | ||
| 50 | |||
| 51 | next_state.pad_state = button_state; | ||
| 52 | next_state.l_stick = stick_state.left; | ||
| 53 | next_state.r_stick = stick_state.right; | ||
| 54 | } | ||
| 55 | |||
| 56 | shared_memory.debug_pad_lifo.WriteNextEntry(next_state); | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h deleted file mode 100644 index dd00b2402..000000000 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ /dev/null | |||
| @@ -1,36 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/debug_pad_types.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | class HIDCore; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Core::Timing { | ||
| 14 | class CoreTiming; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Service::HID { | ||
| 18 | class DebugPad final : public ControllerBase { | ||
| 19 | public: | ||
| 20 | explicit DebugPad(Core::HID::HIDCore& hid_core_); | ||
| 21 | ~DebugPad() override; | ||
| 22 | |||
| 23 | // Called when the controller is initialized | ||
| 24 | void OnInit() override; | ||
| 25 | |||
| 26 | // When the controller is released | ||
| 27 | void OnRelease() override; | ||
| 28 | |||
| 29 | // When the controller is requesting an update for the shared memory | ||
| 30 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 31 | |||
| 32 | private: | ||
| 33 | DebugPadState next_state{}; | ||
| 34 | Core::HID::EmulatedController* controller = nullptr; | ||
| 35 | }; | ||
| 36 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/digitizer.cpp b/src/core/hle/service/hid/controllers/digitizer.cpp deleted file mode 100644 index d5514c965..000000000 --- a/src/core/hle/service/hid/controllers/digitizer.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/digitizer.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | Digitizer::Digitizer(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | Digitizer::~Digitizer() = default; | ||
| 14 | |||
| 15 | void Digitizer::OnInit() {} | ||
| 16 | |||
| 17 | void Digitizer::OnRelease() {} | ||
| 18 | |||
| 19 | void Digitizer::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->digitizer.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/digitizer.h b/src/core/hle/service/hid/controllers/digitizer.h deleted file mode 100644 index d81f814c3..000000000 --- a/src/core/hle/service/hid/controllers/digitizer.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class Digitizer final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit Digitizer(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~Digitizer() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp deleted file mode 100644 index c73da13ee..000000000 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ /dev/null | |||
| @@ -1,366 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/math_util.h" | ||
| 5 | #include "common/settings.h" | ||
| 6 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "core/hid/emulated_console.h" | ||
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 10 | #include "core/hle/service/hid/controllers/gesture.h" | ||
| 11 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | // HW is around 700, value is set to 400 to make it easier to trigger with mouse | ||
| 15 | constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s | ||
| 16 | constexpr f32 angle_threshold = 0.015f; // Threshold in radians | ||
| 17 | constexpr f32 pinch_threshold = 0.5f; // Threshold in pixels | ||
| 18 | constexpr f32 press_delay = 0.5f; // Time in seconds | ||
| 19 | constexpr f32 double_tap_delay = 0.35f; // Time in seconds | ||
| 20 | |||
| 21 | constexpr f32 Square(s32 num) { | ||
| 22 | return static_cast<f32>(num * num); | ||
| 23 | } | ||
| 24 | |||
| 25 | Gesture::Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { | ||
| 26 | console = hid_core.GetEmulatedConsole(); | ||
| 27 | } | ||
| 28 | Gesture::~Gesture() = default; | ||
| 29 | |||
| 30 | void Gesture::OnInit() { | ||
| 31 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 32 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 33 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 34 | |||
| 35 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 36 | return; | ||
| 37 | } | ||
| 38 | |||
| 39 | shared_memory = &data->shared_memory_format->gesture; | ||
| 40 | shared_memory->gesture_lifo.buffer_count = 0; | ||
| 41 | shared_memory->gesture_lifo.buffer_tail = 0; | ||
| 42 | force_update = true; | ||
| 43 | } | ||
| 44 | |||
| 45 | void Gesture::OnRelease() {} | ||
| 46 | |||
| 47 | void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 48 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 49 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 50 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 51 | |||
| 52 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | shared_memory = &data->shared_memory_format->gesture; | ||
| 57 | |||
| 58 | if (!IsControllerActivated()) { | ||
| 59 | shared_memory->gesture_lifo.buffer_count = 0; | ||
| 60 | shared_memory->gesture_lifo.buffer_tail = 0; | ||
| 61 | return; | ||
| 62 | } | ||
| 63 | |||
| 64 | ReadTouchInput(); | ||
| 65 | |||
| 66 | GestureProperties gesture = GetGestureProperties(); | ||
| 67 | f32 time_difference = | ||
| 68 | static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / | ||
| 69 | (1000 * 1000 * 1000); | ||
| 70 | |||
| 71 | // Only update if necessary | ||
| 72 | if (!ShouldUpdateGesture(gesture, time_difference)) { | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | last_update_timestamp = shared_memory->gesture_lifo.timestamp; | ||
| 77 | UpdateGestureSharedMemory(gesture, time_difference); | ||
| 78 | } | ||
| 79 | |||
| 80 | void Gesture::ReadTouchInput() { | ||
| 81 | if (!Settings::values.touchscreen.enabled) { | ||
| 82 | fingers = {}; | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | const auto touch_status = console->GetTouch(); | ||
| 87 | for (std::size_t id = 0; id < fingers.size(); ++id) { | ||
| 88 | fingers[id] = touch_status[id]; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) { | ||
| 93 | const auto& last_entry = GetLastGestureEntry(); | ||
| 94 | if (force_update) { | ||
| 95 | force_update = false; | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | |||
| 99 | // Update if coordinates change | ||
| 100 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 101 | if (gesture.points[id] != last_gesture.points[id]) { | ||
| 102 | return true; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | // Update on press and hold event after 0.5 seconds | ||
| 107 | if (last_entry.type == GestureType::Touch && last_entry.point_count == 1 && | ||
| 108 | time_difference > press_delay) { | ||
| 109 | return enable_press_and_tap; | ||
| 110 | } | ||
| 111 | |||
| 112 | return false; | ||
| 113 | } | ||
| 114 | |||
| 115 | void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) { | ||
| 116 | GestureType type = GestureType::Idle; | ||
| 117 | GestureAttribute attributes{}; | ||
| 118 | |||
| 119 | const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state; | ||
| 120 | |||
| 121 | // Reset next state to default | ||
| 122 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 123 | next_state.delta = {}; | ||
| 124 | next_state.vel_x = 0; | ||
| 125 | next_state.vel_y = 0; | ||
| 126 | next_state.direction = GestureDirection::None; | ||
| 127 | next_state.rotation_angle = 0; | ||
| 128 | next_state.scale = 0; | ||
| 129 | |||
| 130 | if (gesture.active_points > 0) { | ||
| 131 | if (last_gesture.active_points == 0) { | ||
| 132 | NewGesture(gesture, type, attributes); | ||
| 133 | } else { | ||
| 134 | UpdateExistingGesture(gesture, type, time_difference); | ||
| 135 | } | ||
| 136 | } else { | ||
| 137 | EndGesture(gesture, last_gesture, type, attributes, time_difference); | ||
| 138 | } | ||
| 139 | |||
| 140 | // Apply attributes | ||
| 141 | next_state.detection_count = gesture.detection_count; | ||
| 142 | next_state.type = type; | ||
| 143 | next_state.attributes = attributes; | ||
| 144 | next_state.pos = gesture.mid_point; | ||
| 145 | next_state.point_count = static_cast<s32>(gesture.active_points); | ||
| 146 | next_state.points = gesture.points; | ||
| 147 | last_gesture = gesture; | ||
| 148 | |||
| 149 | shared_memory->gesture_lifo.WriteNextEntry(next_state); | ||
| 150 | } | ||
| 151 | |||
| 152 | void Gesture::NewGesture(GestureProperties& gesture, GestureType& type, | ||
| 153 | GestureAttribute& attributes) { | ||
| 154 | const auto& last_entry = GetLastGestureEntry(); | ||
| 155 | |||
| 156 | gesture.detection_count++; | ||
| 157 | type = GestureType::Touch; | ||
| 158 | |||
| 159 | // New touch after cancel is not considered new | ||
| 160 | if (last_entry.type != GestureType::Cancel) { | ||
| 161 | attributes.is_new_touch.Assign(1); | ||
| 162 | enable_press_and_tap = true; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, | ||
| 167 | f32 time_difference) { | ||
| 168 | const auto& last_entry = GetLastGestureEntry(); | ||
| 169 | |||
| 170 | // Promote to pan type if touch moved | ||
| 171 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 172 | if (gesture.points[id] != last_gesture.points[id]) { | ||
| 173 | type = GestureType::Pan; | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | // Number of fingers changed cancel the last event and clear data | ||
| 179 | if (gesture.active_points != last_gesture.active_points) { | ||
| 180 | type = GestureType::Cancel; | ||
| 181 | enable_press_and_tap = false; | ||
| 182 | gesture.active_points = 0; | ||
| 183 | gesture.mid_point = {}; | ||
| 184 | gesture.points.fill({}); | ||
| 185 | return; | ||
| 186 | } | ||
| 187 | |||
| 188 | // Calculate extra parameters of panning | ||
| 189 | if (type == GestureType::Pan) { | ||
| 190 | UpdatePanEvent(gesture, last_gesture, type, time_difference); | ||
| 191 | return; | ||
| 192 | } | ||
| 193 | |||
| 194 | // Promote to press type | ||
| 195 | if (last_entry.type == GestureType::Touch) { | ||
| 196 | type = GestureType::Press; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 201 | GestureType& type, GestureAttribute& attributes, f32 time_difference) { | ||
| 202 | const auto& last_entry = GetLastGestureEntry(); | ||
| 203 | |||
| 204 | if (last_gesture_props.active_points != 0) { | ||
| 205 | switch (last_entry.type) { | ||
| 206 | case GestureType::Touch: | ||
| 207 | if (enable_press_and_tap) { | ||
| 208 | SetTapEvent(gesture, last_gesture_props, type, attributes); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | type = GestureType::Cancel; | ||
| 212 | force_update = true; | ||
| 213 | break; | ||
| 214 | case GestureType::Press: | ||
| 215 | case GestureType::Tap: | ||
| 216 | case GestureType::Swipe: | ||
| 217 | case GestureType::Pinch: | ||
| 218 | case GestureType::Rotate: | ||
| 219 | type = GestureType::Complete; | ||
| 220 | force_update = true; | ||
| 221 | break; | ||
| 222 | case GestureType::Pan: | ||
| 223 | EndPanEvent(gesture, last_gesture_props, type, time_difference); | ||
| 224 | break; | ||
| 225 | default: | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | if (last_entry.type == GestureType::Complete || last_entry.type == GestureType::Cancel) { | ||
| 231 | gesture.detection_count++; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 236 | GestureType& type, GestureAttribute& attributes) { | ||
| 237 | type = GestureType::Tap; | ||
| 238 | gesture = last_gesture_props; | ||
| 239 | force_update = true; | ||
| 240 | f32 tap_time_difference = | ||
| 241 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); | ||
| 242 | last_tap_timestamp = last_update_timestamp; | ||
| 243 | if (tap_time_difference < double_tap_delay) { | ||
| 244 | attributes.is_double_tap.Assign(1); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 249 | GestureType& type, f32 time_difference) { | ||
| 250 | const auto& last_entry = GetLastGestureEntry(); | ||
| 251 | |||
| 252 | next_state.delta = gesture.mid_point - last_entry.pos; | ||
| 253 | next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference; | ||
| 254 | next_state.vel_y = static_cast<f32>(next_state.delta.y) / time_difference; | ||
| 255 | last_pan_time_difference = time_difference; | ||
| 256 | |||
| 257 | // Promote to pinch type | ||
| 258 | if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > | ||
| 259 | pinch_threshold) { | ||
| 260 | type = GestureType::Pinch; | ||
| 261 | next_state.scale = gesture.average_distance / last_gesture_props.average_distance; | ||
| 262 | } | ||
| 263 | |||
| 264 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / | ||
| 265 | (1 + (gesture.angle * last_gesture_props.angle))); | ||
| 266 | // Promote to rotate type | ||
| 267 | if (std::abs(angle_between_two_lines) > angle_threshold) { | ||
| 268 | type = GestureType::Rotate; | ||
| 269 | next_state.scale = 0; | ||
| 270 | next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 275 | GestureType& type, f32 time_difference) { | ||
| 276 | const auto& last_entry = GetLastGestureEntry(); | ||
| 277 | next_state.vel_x = | ||
| 278 | static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); | ||
| 279 | next_state.vel_y = | ||
| 280 | static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference); | ||
| 281 | const f32 curr_vel = | ||
| 282 | std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); | ||
| 283 | |||
| 284 | // Set swipe event with parameters | ||
| 285 | if (curr_vel > swipe_threshold) { | ||
| 286 | SetSwipeEvent(gesture, last_gesture_props, type); | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | |||
| 290 | // End panning without swipe | ||
| 291 | type = GestureType::Complete; | ||
| 292 | next_state.vel_x = 0; | ||
| 293 | next_state.vel_y = 0; | ||
| 294 | force_update = true; | ||
| 295 | } | ||
| 296 | |||
| 297 | void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 298 | GestureType& type) { | ||
| 299 | const auto& last_entry = GetLastGestureEntry(); | ||
| 300 | |||
| 301 | type = GestureType::Swipe; | ||
| 302 | gesture = last_gesture_props; | ||
| 303 | force_update = true; | ||
| 304 | next_state.delta = last_entry.delta; | ||
| 305 | |||
| 306 | if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { | ||
| 307 | if (next_state.delta.x > 0) { | ||
| 308 | next_state.direction = GestureDirection::Right; | ||
| 309 | return; | ||
| 310 | } | ||
| 311 | next_state.direction = GestureDirection::Left; | ||
| 312 | return; | ||
| 313 | } | ||
| 314 | if (next_state.delta.y > 0) { | ||
| 315 | next_state.direction = GestureDirection::Down; | ||
| 316 | return; | ||
| 317 | } | ||
| 318 | next_state.direction = GestureDirection::Up; | ||
| 319 | } | ||
| 320 | |||
| 321 | const GestureState& Gesture::GetLastGestureEntry() const { | ||
| 322 | return shared_memory->gesture_lifo.ReadCurrentEntry().state; | ||
| 323 | } | ||
| 324 | |||
| 325 | GestureProperties Gesture::GetGestureProperties() { | ||
| 326 | GestureProperties gesture; | ||
| 327 | std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; | ||
| 328 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 329 | [](const auto& finger) { return finger.pressed; }); | ||
| 330 | gesture.active_points = | ||
| 331 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 332 | |||
| 333 | for (size_t id = 0; id < gesture.active_points; ++id) { | ||
| 334 | const auto& [active_x, active_y] = active_fingers[id].position; | ||
| 335 | gesture.points[id] = { | ||
| 336 | .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width), | ||
| 337 | .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height), | ||
| 338 | }; | ||
| 339 | |||
| 340 | // Hack: There is no touch in docked but games still allow it | ||
| 341 | if (Settings::IsDockedMode()) { | ||
| 342 | gesture.points[id] = { | ||
| 343 | .x = static_cast<s32>(active_x * Layout::ScreenDocked::Width), | ||
| 344 | .y = static_cast<s32>(active_y * Layout::ScreenDocked::Height), | ||
| 345 | }; | ||
| 346 | } | ||
| 347 | |||
| 348 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); | ||
| 349 | gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points); | ||
| 350 | } | ||
| 351 | |||
| 352 | for (size_t id = 0; id < gesture.active_points; ++id) { | ||
| 353 | const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) + | ||
| 354 | Square(gesture.mid_point.y - gesture.points[id].y)); | ||
| 355 | gesture.average_distance += distance / static_cast<f32>(gesture.active_points); | ||
| 356 | } | ||
| 357 | |||
| 358 | gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y), | ||
| 359 | static_cast<f32>(gesture.mid_point.x - gesture.points[0].x)); | ||
| 360 | |||
| 361 | gesture.detection_count = last_gesture.detection_count; | ||
| 362 | |||
| 363 | return gesture; | ||
| 364 | } | ||
| 365 | |||
| 366 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h deleted file mode 100644 index 78da1552a..000000000 --- a/src/core/hle/service/hid/controllers/gesture.h +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/touch_types.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedConsole; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | struct GestureSharedMemoryFormat; | ||
| 18 | |||
| 19 | class Gesture final : public ControllerBase { | ||
| 20 | public: | ||
| 21 | explicit Gesture(Core::HID::HIDCore& hid_core_); | ||
| 22 | ~Gesture() override; | ||
| 23 | |||
| 24 | // Called when the controller is initialized | ||
| 25 | void OnInit() override; | ||
| 26 | |||
| 27 | // When the controller is released | ||
| 28 | void OnRelease() override; | ||
| 29 | |||
| 30 | // When the controller is requesting an update for the shared memory | ||
| 31 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 32 | |||
| 33 | private: | ||
| 34 | // Reads input from all available input engines | ||
| 35 | void ReadTouchInput(); | ||
| 36 | |||
| 37 | // Returns true if gesture state needs to be updated | ||
| 38 | bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference); | ||
| 39 | |||
| 40 | // Updates the shared memory to the next state | ||
| 41 | void UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference); | ||
| 42 | |||
| 43 | // Initializes new gesture | ||
| 44 | void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes); | ||
| 45 | |||
| 46 | // Updates existing gesture state | ||
| 47 | void UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference); | ||
| 48 | |||
| 49 | // Terminates exiting gesture | ||
| 50 | void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 51 | GestureType& type, GestureAttribute& attributes, f32 time_difference); | ||
| 52 | |||
| 53 | // Set current event to a tap event | ||
| 54 | void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 55 | GestureType& type, GestureAttribute& attributes); | ||
| 56 | |||
| 57 | // Calculates and set the extra parameters related to a pan event | ||
| 58 | void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 59 | GestureType& type, f32 time_difference); | ||
| 60 | |||
| 61 | // Terminates the pan event | ||
| 62 | void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 63 | GestureType& type, f32 time_difference); | ||
| 64 | |||
| 65 | // Set current event to a swipe event | ||
| 66 | void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 67 | GestureType& type); | ||
| 68 | |||
| 69 | // Retrieves the last gesture entry, as indicated by shared memory indices. | ||
| 70 | [[nodiscard]] const GestureState& GetLastGestureEntry() const; | ||
| 71 | |||
| 72 | // Returns the average distance, angle and middle point of the active fingers | ||
| 73 | GestureProperties GetGestureProperties(); | ||
| 74 | |||
| 75 | GestureState next_state{}; | ||
| 76 | GestureSharedMemoryFormat* shared_memory; | ||
| 77 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 78 | |||
| 79 | std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{}; | ||
| 80 | GestureProperties last_gesture{}; | ||
| 81 | s64 last_update_timestamp{}; | ||
| 82 | s64 last_tap_timestamp{}; | ||
| 83 | f32 last_pan_time_difference{}; | ||
| 84 | bool force_update{false}; | ||
| 85 | bool enable_press_and_tap{false}; | ||
| 86 | }; | ||
| 87 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/home_button.cpp b/src/core/hle/service/hid/controllers/home_button.cpp deleted file mode 100644 index 1397379f3..000000000 --- a/src/core/hle/service/hid/controllers/home_button.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/home_button.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | HomeButton::HomeButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | HomeButton::~HomeButton() = default; | ||
| 14 | |||
| 15 | void HomeButton::OnInit() {} | ||
| 16 | |||
| 17 | void HomeButton::OnRelease() {} | ||
| 18 | |||
| 19 | void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->home_button.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/home_button.h b/src/core/hle/service/hid/controllers/home_button.h deleted file mode 100644 index e91c2aa5d..000000000 --- a/src/core/hle/service/hid/controllers/home_button.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class HomeButton final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit HomeButton(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~HomeButton() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp deleted file mode 100644 index c069bcbb2..000000000 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ /dev/null | |||
| @@ -1,56 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_devices.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 9 | #include "core/hle/service/hid/controllers/keyboard.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | Keyboard::Keyboard(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 15 | emulated_devices = hid_core.GetEmulatedDevices(); | ||
| 16 | } | ||
| 17 | |||
| 18 | Keyboard::~Keyboard() = default; | ||
| 19 | |||
| 20 | void Keyboard::OnInit() {} | ||
| 21 | |||
| 22 | void Keyboard::OnRelease() {} | ||
| 23 | |||
| 24 | void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 25 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 26 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 27 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 28 | |||
| 29 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | KeyboardSharedMemoryFormat& shared_memory = data->shared_memory_format->keyboard; | ||
| 34 | |||
| 35 | if (!IsControllerActivated()) { | ||
| 36 | shared_memory.keyboard_lifo.buffer_count = 0; | ||
| 37 | shared_memory.keyboard_lifo.buffer_tail = 0; | ||
| 38 | return; | ||
| 39 | } | ||
| 40 | |||
| 41 | const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state; | ||
| 42 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 43 | |||
| 44 | if (Settings::values.keyboard_enabled) { | ||
| 45 | const auto& keyboard_state = emulated_devices->GetKeyboard(); | ||
| 46 | const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier(); | ||
| 47 | |||
| 48 | next_state.key = keyboard_state; | ||
| 49 | next_state.modifier = keyboard_modifier_state; | ||
| 50 | next_state.attribute.is_connected.Assign(1); | ||
| 51 | } | ||
| 52 | |||
| 53 | shared_memory.keyboard_lifo.WriteNextEntry(next_state); | ||
| 54 | } | ||
| 55 | |||
| 56 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h deleted file mode 100644 index e8ca326c6..000000000 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ /dev/null | |||
| @@ -1,28 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/keyboard_types.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | class Keyboard final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit Keyboard(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~Keyboard() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | KeyboardState next_state{}; | ||
| 26 | Core::HID::EmulatedDevices* emulated_devices = nullptr; | ||
| 27 | }; | ||
| 28 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp deleted file mode 100644 index 3a8d1751b..000000000 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/frontend/emu_window.h" | ||
| 6 | #include "core/hid/emulated_devices.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 9 | #include "core/hle/service/hid/controllers/mouse.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | Mouse::Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 15 | emulated_devices = hid_core.GetEmulatedDevices(); | ||
| 16 | } | ||
| 17 | |||
| 18 | Mouse::~Mouse() = default; | ||
| 19 | |||
| 20 | void Mouse::OnInit() {} | ||
| 21 | void Mouse::OnRelease() {} | ||
| 22 | |||
| 23 | void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | MouseSharedMemoryFormat& shared_memory = data->shared_memory_format->mouse; | ||
| 33 | |||
| 34 | if (!IsControllerActivated()) { | ||
| 35 | shared_memory.mouse_lifo.buffer_count = 0; | ||
| 36 | shared_memory.mouse_lifo.buffer_tail = 0; | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | |||
| 40 | next_state = {}; | ||
| 41 | |||
| 42 | const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; | ||
| 43 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 44 | |||
| 45 | if (Settings::values.mouse_enabled) { | ||
| 46 | const auto& mouse_button_state = emulated_devices->GetMouseButtons(); | ||
| 47 | const auto& mouse_position_state = emulated_devices->GetMousePosition(); | ||
| 48 | const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); | ||
| 49 | next_state.attribute.is_connected.Assign(1); | ||
| 50 | next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); | ||
| 51 | next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); | ||
| 52 | next_state.delta_x = next_state.x - last_entry.x; | ||
| 53 | next_state.delta_y = next_state.y - last_entry.y; | ||
| 54 | next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; | ||
| 55 | next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; | ||
| 56 | |||
| 57 | last_mouse_wheel_state = mouse_wheel_state; | ||
| 58 | next_state.button = mouse_button_state; | ||
| 59 | } | ||
| 60 | |||
| 61 | shared_memory.mouse_lifo.WriteNextEntry(next_state); | ||
| 62 | } | ||
| 63 | |||
| 64 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h deleted file mode 100644 index cefad956c..000000000 --- a/src/core/hle/service/hid/controllers/mouse.h +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | class EmulatedDevices; | ||
| 10 | struct MouseState; | ||
| 11 | struct AnalogStickState; | ||
| 12 | } // namespace Core::HID | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | class Mouse final : public ControllerBase { | ||
| 16 | public: | ||
| 17 | explicit Mouse(Core::HID::HIDCore& hid_core_); | ||
| 18 | ~Mouse() override; | ||
| 19 | |||
| 20 | // Called when the controller is initialized | ||
| 21 | void OnInit() override; | ||
| 22 | |||
| 23 | // When the controller is released | ||
| 24 | void OnRelease() override; | ||
| 25 | |||
| 26 | // When the controller is requesting an update for the shared memory | ||
| 27 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 28 | |||
| 29 | private: | ||
| 30 | Core::HID::MouseState next_state{}; | ||
| 31 | Core::HID::AnalogStickState last_mouse_wheel_state{}; | ||
| 32 | Core::HID::EmulatedDevices* emulated_devices = nullptr; | ||
| 33 | }; | ||
| 34 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp deleted file mode 100644 index 17cd0d7a0..000000000 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ /dev/null | |||
| @@ -1,1342 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <array> | ||
| 6 | #include <chrono> | ||
| 7 | #include <cstring> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | #include "common/settings.h" | ||
| 14 | #include "core/core_timing.h" | ||
| 15 | #include "core/hid/emulated_controller.h" | ||
| 16 | #include "core/hid/hid_core.h" | ||
| 17 | #include "core/hle/kernel/k_event.h" | ||
| 18 | #include "core/hle/kernel/k_readable_event.h" | ||
| 19 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 20 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 21 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 22 | #include "core/hle/service/hid/errors.h" | ||
| 23 | #include "core/hle/service/hid/hid_util.h" | ||
| 24 | #include "core/hle/service/kernel_helpers.h" | ||
| 25 | |||
| 26 | namespace Service::HID { | ||
| 27 | |||
| 28 | NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) | ||
| 29 | : hid_core{hid_core_}, service_context{service_context_}, npad_resource{service_context} { | ||
| 30 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { | ||
| 31 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 32 | auto& controller = controller_data[aruid_index][i]; | ||
| 33 | controller.device = hid_core.GetEmulatedControllerByIndex(i); | ||
| 34 | controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = | ||
| 35 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 36 | controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] | ||
| 37 | .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 38 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 39 | .on_change = | ||
| 40 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, | ||
| 41 | .is_npad_service = true, | ||
| 42 | }; | ||
| 43 | controller.callback_key = controller.device->SetCallback(engine_callback); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | NPad::~NPad() { | ||
| 49 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { | ||
| 50 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 51 | auto& controller = controller_data[aruid_index][i]; | ||
| 52 | controller.device->DeleteCallback(controller.callback_key); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | Result NPad::Activate() { | ||
| 58 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 59 | return ResultNpadResourceOverflow; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (ref_counter == 0) { | ||
| 63 | std::scoped_lock lock{mutex}; | ||
| 64 | |||
| 65 | // TODO: Activate handlers and AbstractedPad | ||
| 66 | } | ||
| 67 | |||
| 68 | ref_counter++; | ||
| 69 | return ResultSuccess; | ||
| 70 | } | ||
| 71 | |||
| 72 | Result NPad::Activate(u64 aruid) { | ||
| 73 | std::scoped_lock lock{mutex}; | ||
| 74 | std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex}; | ||
| 75 | |||
| 76 | auto* data = applet_resource_holder.applet_resource->GetAruidData(aruid); | ||
| 77 | const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); | ||
| 78 | |||
| 79 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 80 | return ResultSuccess; | ||
| 81 | } | ||
| 82 | |||
| 83 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 84 | auto& controller = controller_data[aruid_index][i]; | ||
| 85 | controller.shared_memory = &data->shared_memory_format->npad.npad_entry[i].internal_state; | ||
| 86 | } | ||
| 87 | |||
| 88 | // Prefill controller buffers | ||
| 89 | for (auto& controller : controller_data[aruid_index]) { | ||
| 90 | auto* npad = controller.shared_memory; | ||
| 91 | npad->fullkey_color = { | ||
| 92 | .attribute = ColorAttribute::NoController, | ||
| 93 | .fullkey = {}, | ||
| 94 | }; | ||
| 95 | npad->joycon_color = { | ||
| 96 | .attribute = ColorAttribute::NoController, | ||
| 97 | .left = {}, | ||
| 98 | .right = {}, | ||
| 99 | }; | ||
| 100 | // HW seems to initialize the first 19 entries | ||
| 101 | for (std::size_t i = 0; i < 19; ++i) { | ||
| 102 | WriteEmptyEntry(npad); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | return ResultSuccess; | ||
| 107 | } | ||
| 108 | |||
| 109 | Result NPad::ActivateNpadResource() { | ||
| 110 | return npad_resource.Activate(); | ||
| 111 | } | ||
| 112 | |||
| 113 | Result NPad::ActivateNpadResource(u64 aruid) { | ||
| 114 | return npad_resource.Activate(aruid); | ||
| 115 | } | ||
| 116 | |||
| 117 | void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { | ||
| 118 | if (type == Core::HID::ControllerTriggerType::All) { | ||
| 119 | ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); | ||
| 120 | ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); | ||
| 121 | return; | ||
| 122 | } | ||
| 123 | |||
| 124 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 125 | if (controller_idx >= controller_data[aruid_index].size()) { | ||
| 126 | return; | ||
| 127 | } | ||
| 128 | |||
| 129 | auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 130 | |||
| 131 | if (!data->flag.is_assigned) { | ||
| 132 | continue; | ||
| 133 | } | ||
| 134 | |||
| 135 | auto& controller = controller_data[aruid_index][controller_idx]; | ||
| 136 | const auto is_connected = controller.device->IsConnected(); | ||
| 137 | const auto npad_type = controller.device->GetNpadStyleIndex(); | ||
| 138 | const auto npad_id = controller.device->GetNpadIdType(); | ||
| 139 | switch (type) { | ||
| 140 | case Core::HID::ControllerTriggerType::Connected: | ||
| 141 | case Core::HID::ControllerTriggerType::Disconnected: | ||
| 142 | if (is_connected == controller.is_connected) { | ||
| 143 | return; | ||
| 144 | } | ||
| 145 | UpdateControllerAt(data->aruid, npad_type, npad_id, is_connected); | ||
| 146 | break; | ||
| 147 | case Core::HID::ControllerTriggerType::Battery: { | ||
| 148 | if (!controller.device->IsConnected()) { | ||
| 149 | return; | ||
| 150 | } | ||
| 151 | auto* shared_memory = controller.shared_memory; | ||
| 152 | const auto& battery_level = controller.device->GetBattery(); | ||
| 153 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | ||
| 154 | shared_memory->battery_level_left = battery_level.left.battery_level; | ||
| 155 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | default: | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 165 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 166 | if (!npad_resource.IsControllerSupported(aruid, controller.device->GetNpadStyleIndex())) { | ||
| 167 | return; | ||
| 168 | } | ||
| 169 | LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); | ||
| 170 | const auto controller_type = controller.device->GetNpadStyleIndex(); | ||
| 171 | const auto& body_colors = controller.device->GetColors(); | ||
| 172 | const auto& battery_level = controller.device->GetBattery(); | ||
| 173 | auto* shared_memory = controller.shared_memory; | ||
| 174 | if (controller_type == Core::HID::NpadStyleIndex::None) { | ||
| 175 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | |||
| 179 | // Reset memory values | ||
| 180 | shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; | ||
| 181 | shared_memory->device_type.raw = 0; | ||
| 182 | shared_memory->system_properties.raw = 0; | ||
| 183 | shared_memory->joycon_color.attribute = ColorAttribute::NoController; | ||
| 184 | shared_memory->joycon_color.attribute = ColorAttribute::NoController; | ||
| 185 | shared_memory->fullkey_color = {}; | ||
| 186 | shared_memory->joycon_color.left = {}; | ||
| 187 | shared_memory->joycon_color.right = {}; | ||
| 188 | shared_memory->battery_level_dual = {}; | ||
| 189 | shared_memory->battery_level_left = {}; | ||
| 190 | shared_memory->battery_level_right = {}; | ||
| 191 | |||
| 192 | switch (controller_type) { | ||
| 193 | case Core::HID::NpadStyleIndex::None: | ||
| 194 | ASSERT(false); | ||
| 195 | break; | ||
| 196 | case Core::HID::NpadStyleIndex::ProController: | ||
| 197 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 198 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 199 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | ||
| 200 | shared_memory->style_tag.fullkey.Assign(1); | ||
| 201 | shared_memory->device_type.fullkey.Assign(1); | ||
| 202 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 203 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 204 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 205 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 206 | battery_level.dual.is_charging); | ||
| 207 | shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController; | ||
| 208 | shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | ||
| 209 | break; | ||
| 210 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 211 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 212 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 213 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 214 | shared_memory->joycon_color.left = body_colors.left; | ||
| 215 | shared_memory->joycon_color.right = body_colors.right; | ||
| 216 | shared_memory->style_tag.handheld.Assign(1); | ||
| 217 | shared_memory->device_type.handheld_left.Assign(1); | ||
| 218 | shared_memory->device_type.handheld_right.Assign(1); | ||
| 219 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 220 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 221 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 222 | shared_memory->system_properties.use_directional_buttons.Assign(1); | ||
| 223 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 224 | battery_level.left.is_charging); | ||
| 225 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 226 | battery_level.left.is_charging); | ||
| 227 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 228 | battery_level.right.is_charging); | ||
| 229 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | ||
| 230 | shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; | ||
| 231 | shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); | ||
| 232 | break; | ||
| 233 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 234 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 235 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 236 | shared_memory->style_tag.joycon_dual.Assign(1); | ||
| 237 | if (controller.is_dual_left_connected) { | ||
| 238 | shared_memory->joycon_color.left = body_colors.left; | ||
| 239 | shared_memory->battery_level_left = battery_level.left.battery_level; | ||
| 240 | shared_memory->device_type.joycon_left.Assign(1); | ||
| 241 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 242 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 243 | battery_level.left.is_charging); | ||
| 244 | shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); | ||
| 245 | } | ||
| 246 | if (controller.is_dual_right_connected) { | ||
| 247 | shared_memory->joycon_color.right = body_colors.right; | ||
| 248 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 249 | shared_memory->device_type.joycon_right.Assign(1); | ||
| 250 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 251 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 252 | battery_level.right.is_charging); | ||
| 253 | shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); | ||
| 254 | } | ||
| 255 | shared_memory->system_properties.use_directional_buttons.Assign(1); | ||
| 256 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 257 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | ||
| 258 | |||
| 259 | if (controller.is_dual_left_connected && controller.is_dual_right_connected) { | ||
| 260 | shared_memory->applet_footer_type = AppletFooterUiType::JoyDual; | ||
| 261 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 262 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 263 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 264 | battery_level.left.is_charging); | ||
| 265 | } else if (controller.is_dual_left_connected) { | ||
| 266 | shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly; | ||
| 267 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 268 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 269 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 270 | battery_level.left.is_charging); | ||
| 271 | } else { | ||
| 272 | shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly; | ||
| 273 | shared_memory->fullkey_color.fullkey = body_colors.right; | ||
| 274 | shared_memory->battery_level_dual = battery_level.right.battery_level; | ||
| 275 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 276 | battery_level.right.is_charging); | ||
| 277 | } | ||
| 278 | break; | ||
| 279 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 280 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 281 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 282 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 283 | shared_memory->joycon_color.left = body_colors.left; | ||
| 284 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 285 | shared_memory->style_tag.joycon_left.Assign(1); | ||
| 286 | shared_memory->device_type.joycon_left.Assign(1); | ||
| 287 | shared_memory->system_properties.is_horizontal.Assign(1); | ||
| 288 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 289 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 290 | battery_level.left.is_charging); | ||
| 291 | shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal; | ||
| 292 | shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); | ||
| 293 | break; | ||
| 294 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 295 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 296 | shared_memory->fullkey_color.fullkey = body_colors.right; | ||
| 297 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 298 | shared_memory->joycon_color.right = body_colors.right; | ||
| 299 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 300 | shared_memory->style_tag.joycon_right.Assign(1); | ||
| 301 | shared_memory->device_type.joycon_right.Assign(1); | ||
| 302 | shared_memory->system_properties.is_horizontal.Assign(1); | ||
| 303 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 304 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 305 | battery_level.right.is_charging); | ||
| 306 | shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal; | ||
| 307 | shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); | ||
| 308 | break; | ||
| 309 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 310 | shared_memory->style_tag.gamecube.Assign(1); | ||
| 311 | shared_memory->device_type.fullkey.Assign(1); | ||
| 312 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 313 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 314 | break; | ||
| 315 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 316 | shared_memory->style_tag.palma.Assign(1); | ||
| 317 | shared_memory->device_type.palma.Assign(1); | ||
| 318 | shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | ||
| 319 | break; | ||
| 320 | case Core::HID::NpadStyleIndex::NES: | ||
| 321 | shared_memory->style_tag.lark.Assign(1); | ||
| 322 | shared_memory->device_type.fullkey.Assign(1); | ||
| 323 | break; | ||
| 324 | case Core::HID::NpadStyleIndex::SNES: | ||
| 325 | shared_memory->style_tag.lucia.Assign(1); | ||
| 326 | shared_memory->device_type.fullkey.Assign(1); | ||
| 327 | shared_memory->applet_footer_type = AppletFooterUiType::Lucia; | ||
| 328 | break; | ||
| 329 | case Core::HID::NpadStyleIndex::N64: | ||
| 330 | shared_memory->style_tag.lagoon.Assign(1); | ||
| 331 | shared_memory->device_type.fullkey.Assign(1); | ||
| 332 | shared_memory->applet_footer_type = AppletFooterUiType::Lagon; | ||
| 333 | break; | ||
| 334 | case Core::HID::NpadStyleIndex::SegaGenesis: | ||
| 335 | shared_memory->style_tag.lager.Assign(1); | ||
| 336 | shared_memory->device_type.fullkey.Assign(1); | ||
| 337 | break; | ||
| 338 | default: | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | |||
| 342 | controller.is_connected = true; | ||
| 343 | controller.device->Connect(); | ||
| 344 | controller.device->SetLedPattern(); | ||
| 345 | if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 346 | if (controller.is_dual_left_connected) { | ||
| 347 | controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex, | ||
| 348 | Common::Input::PollingMode::Active); | ||
| 349 | } | ||
| 350 | if (controller.is_dual_right_connected) { | ||
| 351 | controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, | ||
| 352 | Common::Input::PollingMode::Active); | ||
| 353 | } | ||
| 354 | } else { | ||
| 355 | controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, | ||
| 356 | Common::Input::PollingMode::Active); | ||
| 357 | } | ||
| 358 | |||
| 359 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | ||
| 360 | WriteEmptyEntry(controller.shared_memory); | ||
| 361 | hid_core.SetLastActiveController(npad_id); | ||
| 362 | } | ||
| 363 | |||
| 364 | void NPad::WriteEmptyEntry(NpadInternalState* npad) { | ||
| 365 | NPadGenericState dummy_pad_state{}; | ||
| 366 | NpadGcTriggerState dummy_gc_state{}; | ||
| 367 | dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 368 | npad->fullkey_lifo.WriteNextEntry(dummy_pad_state); | ||
| 369 | dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 370 | npad->handheld_lifo.WriteNextEntry(dummy_pad_state); | ||
| 371 | dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 372 | npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state); | ||
| 373 | dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 374 | npad->joy_left_lifo.WriteNextEntry(dummy_pad_state); | ||
| 375 | dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 376 | npad->joy_right_lifo.WriteNextEntry(dummy_pad_state); | ||
| 377 | dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 378 | npad->palma_lifo.WriteNextEntry(dummy_pad_state); | ||
| 379 | dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 380 | npad->system_ext_lifo.WriteNextEntry(dummy_pad_state); | ||
| 381 | dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 382 | npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); | ||
| 383 | } | ||
| 384 | |||
| 385 | void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 386 | std::scoped_lock lock{*applet_resource_holder.shared_mutex}; | ||
| 387 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 388 | const auto controller_type = controller.device->GetNpadStyleIndex(); | ||
| 389 | |||
| 390 | if (!controller.device->IsConnected() && controller.is_connected) { | ||
| 391 | DisconnectNpad(aruid, npad_id); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | if (!controller.device->IsConnected()) { | ||
| 395 | return; | ||
| 396 | } | ||
| 397 | if (controller.device->IsConnected() && !controller.is_connected) { | ||
| 398 | InitNewlyAddedController(aruid, npad_id); | ||
| 399 | } | ||
| 400 | |||
| 401 | // This function is unique to yuzu for the turbo buttons and motion to work properly | ||
| 402 | controller.device->StatusUpdate(); | ||
| 403 | |||
| 404 | auto& pad_entry = controller.npad_pad_state; | ||
| 405 | auto& trigger_entry = controller.npad_trigger_state; | ||
| 406 | const auto button_state = controller.device->GetNpadButtons(); | ||
| 407 | const auto stick_state = controller.device->GetSticks(); | ||
| 408 | |||
| 409 | using btn = Core::HID::NpadButton; | ||
| 410 | pad_entry.npad_buttons.raw = btn::None; | ||
| 411 | if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { | ||
| 412 | constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | | ||
| 413 | btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | | ||
| 414 | btn::StickRRight | btn::StickRDown; | ||
| 415 | pad_entry.npad_buttons.raw = button_state.raw & right_button_mask; | ||
| 416 | pad_entry.r_stick = stick_state.right; | ||
| 417 | } | ||
| 418 | |||
| 419 | if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 420 | constexpr btn left_button_mask = | ||
| 421 | btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | | ||
| 422 | btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; | ||
| 423 | pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask; | ||
| 424 | pad_entry.l_stick = stick_state.left; | ||
| 425 | } | ||
| 426 | |||
| 427 | if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft || | ||
| 428 | controller_type == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 429 | pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); | ||
| 430 | pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); | ||
| 431 | } | ||
| 432 | |||
| 433 | if (controller_type == Core::HID::NpadStyleIndex::JoyconRight || | ||
| 434 | controller_type == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 435 | pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); | ||
| 436 | pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); | ||
| 437 | } | ||
| 438 | |||
| 439 | if (controller_type == Core::HID::NpadStyleIndex::GameCube) { | ||
| 440 | const auto& trigger_state = controller.device->GetTriggers(); | ||
| 441 | trigger_entry.l_analog = trigger_state.left; | ||
| 442 | trigger_entry.r_analog = trigger_state.right; | ||
| 443 | pad_entry.npad_buttons.zl.Assign(false); | ||
| 444 | pad_entry.npad_buttons.zr.Assign(button_state.r); | ||
| 445 | pad_entry.npad_buttons.l.Assign(button_state.zl); | ||
| 446 | pad_entry.npad_buttons.r.Assign(button_state.zr); | ||
| 447 | } | ||
| 448 | |||
| 449 | if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) { | ||
| 450 | hid_core.SetLastActiveController(npad_id); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 455 | if (ref_counter == 0) { | ||
| 456 | return; | ||
| 457 | } | ||
| 458 | |||
| 459 | std::scoped_lock lock{*applet_resource_holder.shared_mutex}; | ||
| 460 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { | ||
| 461 | const auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 462 | const auto aruid = data->aruid; | ||
| 463 | |||
| 464 | if (!data->flag.is_assigned) { | ||
| 465 | continue; | ||
| 466 | } | ||
| 467 | |||
| 468 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 469 | auto& controller = controller_data[aruid_index][i]; | ||
| 470 | controller.shared_memory = | ||
| 471 | &data->shared_memory_format->npad.npad_entry[i].internal_state; | ||
| 472 | auto* npad = controller.shared_memory; | ||
| 473 | |||
| 474 | const auto& controller_type = controller.device->GetNpadStyleIndex(); | ||
| 475 | |||
| 476 | if (controller_type == Core::HID::NpadStyleIndex::None || | ||
| 477 | !controller.device->IsConnected()) { | ||
| 478 | continue; | ||
| 479 | } | ||
| 480 | |||
| 481 | RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); | ||
| 482 | auto& pad_state = controller.npad_pad_state; | ||
| 483 | auto& libnx_state = controller.npad_libnx_state; | ||
| 484 | auto& trigger_state = controller.npad_trigger_state; | ||
| 485 | |||
| 486 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't | ||
| 487 | // activate any controllers. | ||
| 488 | libnx_state.connection_status.raw = 0; | ||
| 489 | libnx_state.connection_status.is_connected.Assign(1); | ||
| 490 | switch (controller_type) { | ||
| 491 | case Core::HID::NpadStyleIndex::None: | ||
| 492 | ASSERT(false); | ||
| 493 | break; | ||
| 494 | case Core::HID::NpadStyleIndex::ProController: | ||
| 495 | case Core::HID::NpadStyleIndex::NES: | ||
| 496 | case Core::HID::NpadStyleIndex::SNES: | ||
| 497 | case Core::HID::NpadStyleIndex::N64: | ||
| 498 | case Core::HID::NpadStyleIndex::SegaGenesis: | ||
| 499 | pad_state.connection_status.raw = 0; | ||
| 500 | pad_state.connection_status.is_connected.Assign(1); | ||
| 501 | pad_state.connection_status.is_wired.Assign(1); | ||
| 502 | |||
| 503 | libnx_state.connection_status.is_wired.Assign(1); | ||
| 504 | pad_state.sampling_number = | ||
| 505 | npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 506 | npad->fullkey_lifo.WriteNextEntry(pad_state); | ||
| 507 | break; | ||
| 508 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 509 | pad_state.connection_status.raw = 0; | ||
| 510 | pad_state.connection_status.is_connected.Assign(1); | ||
| 511 | pad_state.connection_status.is_wired.Assign(1); | ||
| 512 | pad_state.connection_status.is_left_connected.Assign(1); | ||
| 513 | pad_state.connection_status.is_right_connected.Assign(1); | ||
| 514 | pad_state.connection_status.is_left_wired.Assign(1); | ||
| 515 | pad_state.connection_status.is_right_wired.Assign(1); | ||
| 516 | |||
| 517 | libnx_state.connection_status.is_wired.Assign(1); | ||
| 518 | libnx_state.connection_status.is_left_connected.Assign(1); | ||
| 519 | libnx_state.connection_status.is_right_connected.Assign(1); | ||
| 520 | libnx_state.connection_status.is_left_wired.Assign(1); | ||
| 521 | libnx_state.connection_status.is_right_wired.Assign(1); | ||
| 522 | pad_state.sampling_number = | ||
| 523 | npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 524 | npad->handheld_lifo.WriteNextEntry(pad_state); | ||
| 525 | break; | ||
| 526 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 527 | pad_state.connection_status.raw = 0; | ||
| 528 | pad_state.connection_status.is_connected.Assign(1); | ||
| 529 | if (controller.is_dual_left_connected) { | ||
| 530 | pad_state.connection_status.is_left_connected.Assign(1); | ||
| 531 | libnx_state.connection_status.is_left_connected.Assign(1); | ||
| 532 | } | ||
| 533 | if (controller.is_dual_right_connected) { | ||
| 534 | pad_state.connection_status.is_right_connected.Assign(1); | ||
| 535 | libnx_state.connection_status.is_right_connected.Assign(1); | ||
| 536 | } | ||
| 537 | |||
| 538 | pad_state.sampling_number = | ||
| 539 | npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 540 | npad->joy_dual_lifo.WriteNextEntry(pad_state); | ||
| 541 | break; | ||
| 542 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 543 | pad_state.connection_status.raw = 0; | ||
| 544 | pad_state.connection_status.is_connected.Assign(1); | ||
| 545 | pad_state.connection_status.is_left_connected.Assign(1); | ||
| 546 | |||
| 547 | libnx_state.connection_status.is_left_connected.Assign(1); | ||
| 548 | pad_state.sampling_number = | ||
| 549 | npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 550 | npad->joy_left_lifo.WriteNextEntry(pad_state); | ||
| 551 | break; | ||
| 552 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 553 | pad_state.connection_status.raw = 0; | ||
| 554 | pad_state.connection_status.is_connected.Assign(1); | ||
| 555 | pad_state.connection_status.is_right_connected.Assign(1); | ||
| 556 | |||
| 557 | libnx_state.connection_status.is_right_connected.Assign(1); | ||
| 558 | pad_state.sampling_number = | ||
| 559 | npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 560 | npad->joy_right_lifo.WriteNextEntry(pad_state); | ||
| 561 | break; | ||
| 562 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 563 | pad_state.connection_status.raw = 0; | ||
| 564 | pad_state.connection_status.is_connected.Assign(1); | ||
| 565 | pad_state.connection_status.is_wired.Assign(1); | ||
| 566 | |||
| 567 | libnx_state.connection_status.is_wired.Assign(1); | ||
| 568 | pad_state.sampling_number = | ||
| 569 | npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 570 | trigger_state.sampling_number = | ||
| 571 | npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 572 | npad->fullkey_lifo.WriteNextEntry(pad_state); | ||
| 573 | npad->gc_trigger_lifo.WriteNextEntry(trigger_state); | ||
| 574 | break; | ||
| 575 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 576 | pad_state.connection_status.raw = 0; | ||
| 577 | pad_state.connection_status.is_connected.Assign(1); | ||
| 578 | pad_state.sampling_number = | ||
| 579 | npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 580 | npad->palma_lifo.WriteNextEntry(pad_state); | ||
| 581 | break; | ||
| 582 | default: | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | |||
| 586 | libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; | ||
| 587 | libnx_state.l_stick = pad_state.l_stick; | ||
| 588 | libnx_state.r_stick = pad_state.r_stick; | ||
| 589 | npad->system_ext_lifo.WriteNextEntry(pad_state); | ||
| 590 | |||
| 591 | press_state |= static_cast<u64>(pad_state.npad_buttons.raw); | ||
| 592 | } | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) { | ||
| 597 | std::scoped_lock lock{mutex}; | ||
| 598 | hid_core.SetSupportedStyleTag({supported_style_set}); | ||
| 599 | const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set); | ||
| 600 | if (result.IsSuccess()) { | ||
| 601 | OnUpdate({}); | ||
| 602 | } | ||
| 603 | return result; | ||
| 604 | } | ||
| 605 | |||
| 606 | Result NPad::GetSupportedNpadStyleSet(u64 aruid, | ||
| 607 | Core::HID::NpadStyleSet& out_supported_style_set) const { | ||
| 608 | std::scoped_lock lock{mutex}; | ||
| 609 | const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid); | ||
| 610 | |||
| 611 | if (result == ResultUndefinedStyleset) { | ||
| 612 | out_supported_style_set = Core::HID::NpadStyleSet::None; | ||
| 613 | return ResultSuccess; | ||
| 614 | } | ||
| 615 | |||
| 616 | return result; | ||
| 617 | } | ||
| 618 | |||
| 619 | Result NPad::GetMaskedSupportedNpadStyleSet( | ||
| 620 | u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { | ||
| 621 | std::scoped_lock lock{mutex}; | ||
| 622 | const Result result = | ||
| 623 | npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid); | ||
| 624 | |||
| 625 | if (result == ResultUndefinedStyleset) { | ||
| 626 | out_supported_style_set = Core::HID::NpadStyleSet::None; | ||
| 627 | return ResultSuccess; | ||
| 628 | } | ||
| 629 | |||
| 630 | return result; | ||
| 631 | } | ||
| 632 | |||
| 633 | Result NPad::SetSupportedNpadIdType(u64 aruid, | ||
| 634 | std::span<const Core::HID::NpadIdType> supported_npad_list) { | ||
| 635 | std::scoped_lock lock{mutex}; | ||
| 636 | if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { | ||
| 637 | return ResultInvalidArraySize; | ||
| 638 | } | ||
| 639 | |||
| 640 | Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list); | ||
| 641 | |||
| 642 | if (result.IsSuccess()) { | ||
| 643 | OnUpdate({}); | ||
| 644 | } | ||
| 645 | |||
| 646 | return result; | ||
| 647 | } | ||
| 648 | |||
| 649 | Result NPad::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { | ||
| 650 | std::scoped_lock lock{mutex}; | ||
| 651 | return npad_resource.SetNpadJoyHoldType(aruid, hold_type); | ||
| 652 | } | ||
| 653 | |||
| 654 | Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const { | ||
| 655 | std::scoped_lock lock{mutex}; | ||
| 656 | return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid); | ||
| 657 | } | ||
| 658 | |||
| 659 | Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) { | ||
| 660 | std::scoped_lock lock{mutex}; | ||
| 661 | Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode); | ||
| 662 | if (result.IsSuccess()) { | ||
| 663 | OnUpdate({}); | ||
| 664 | } | ||
| 665 | return result; | ||
| 666 | } | ||
| 667 | |||
| 668 | Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const { | ||
| 669 | std::scoped_lock lock{mutex}; | ||
| 670 | return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid); | ||
| 671 | } | ||
| 672 | |||
| 673 | bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, | ||
| 674 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { | ||
| 675 | if (!IsNpadIdValid(npad_id)) { | ||
| 676 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 677 | return false; | ||
| 678 | } | ||
| 679 | |||
| 680 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 681 | if (controller.shared_memory->assignment_mode != assignment_mode) { | ||
| 682 | controller.shared_memory->assignment_mode = assignment_mode; | ||
| 683 | } | ||
| 684 | |||
| 685 | if (!controller.device->IsConnected()) { | ||
| 686 | return false; | ||
| 687 | } | ||
| 688 | |||
| 689 | if (assignment_mode == NpadJoyAssignmentMode::Dual) { | ||
| 690 | if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { | ||
| 691 | DisconnectNpad(aruid, npad_id); | ||
| 692 | controller.is_dual_left_connected = true; | ||
| 693 | controller.is_dual_right_connected = false; | ||
| 694 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); | ||
| 695 | return false; | ||
| 696 | } | ||
| 697 | if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 698 | DisconnectNpad(aruid, npad_id); | ||
| 699 | controller.is_dual_left_connected = false; | ||
| 700 | controller.is_dual_right_connected = true; | ||
| 701 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); | ||
| 702 | return false; | ||
| 703 | } | ||
| 704 | return false; | ||
| 705 | } | ||
| 706 | |||
| 707 | // This is for NpadJoyAssignmentMode::Single | ||
| 708 | |||
| 709 | // Only JoyconDual get affected by this function | ||
| 710 | if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 711 | return false; | ||
| 712 | } | ||
| 713 | |||
| 714 | if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { | ||
| 715 | DisconnectNpad(aruid, npad_id); | ||
| 716 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); | ||
| 717 | return false; | ||
| 718 | } | ||
| 719 | if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { | ||
| 720 | DisconnectNpad(aruid, npad_id); | ||
| 721 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); | ||
| 722 | return false; | ||
| 723 | } | ||
| 724 | |||
| 725 | // We have two controllers connected to the same npad_id we need to split them | ||
| 726 | new_npad_id = hid_core.GetFirstDisconnectedNpadId(); | ||
| 727 | auto& controller_2 = GetControllerFromNpadIdType(aruid, new_npad_id); | ||
| 728 | DisconnectNpad(aruid, npad_id); | ||
| 729 | if (npad_device_type == NpadJoyDeviceType::Left) { | ||
| 730 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); | ||
| 731 | controller_2.is_dual_left_connected = false; | ||
| 732 | controller_2.is_dual_right_connected = true; | ||
| 733 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); | ||
| 734 | } else { | ||
| 735 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); | ||
| 736 | controller_2.is_dual_left_connected = true; | ||
| 737 | controller_2.is_dual_right_connected = false; | ||
| 738 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); | ||
| 739 | } | ||
| 740 | return true; | ||
| 741 | } | ||
| 742 | |||
| 743 | bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 744 | std::size_t device_index, | ||
| 745 | const Core::HID::VibrationValue& vibration_value) { | ||
| 746 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 747 | if (!controller.device->IsConnected()) { | ||
| 748 | return false; | ||
| 749 | } | ||
| 750 | |||
| 751 | if (!controller.device->IsVibrationEnabled(device_index)) { | ||
| 752 | if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || | ||
| 753 | controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { | ||
| 754 | // Send an empty vibration to stop any vibrations. | ||
| 755 | Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; | ||
| 756 | controller.device->SetVibration(device_index, vibration); | ||
| 757 | // Then reset the vibration value to its default value. | ||
| 758 | controller.vibration[device_index].latest_vibration_value = | ||
| 759 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 760 | } | ||
| 761 | |||
| 762 | return false; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { | ||
| 766 | using std::chrono::duration_cast; | ||
| 767 | using std::chrono::milliseconds; | ||
| 768 | using std::chrono::steady_clock; | ||
| 769 | |||
| 770 | const auto now = steady_clock::now(); | ||
| 771 | |||
| 772 | // Filter out non-zero vibrations that are within 15ms of each other. | ||
| 773 | if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && | ||
| 774 | duration_cast<milliseconds>( | ||
| 775 | now - controller.vibration[device_index].last_vibration_timepoint) < | ||
| 776 | milliseconds(15)) { | ||
| 777 | return false; | ||
| 778 | } | ||
| 779 | |||
| 780 | controller.vibration[device_index].last_vibration_timepoint = now; | ||
| 781 | } | ||
| 782 | |||
| 783 | Core::HID::VibrationValue vibration{ | ||
| 784 | vibration_value.low_amplitude, vibration_value.low_frequency, | ||
| 785 | vibration_value.high_amplitude, vibration_value.high_frequency}; | ||
| 786 | return controller.device->SetVibration(device_index, vibration); | ||
| 787 | } | ||
| 788 | |||
| 789 | void NPad::VibrateController(u64 aruid, | ||
| 790 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 791 | const Core::HID::VibrationValue& vibration_value) { | ||
| 792 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 793 | return; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 801 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 802 | |||
| 803 | if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { | ||
| 804 | return; | ||
| 805 | } | ||
| 806 | |||
| 807 | if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { | ||
| 808 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 809 | return; | ||
| 810 | } | ||
| 811 | |||
| 812 | // Some games try to send mismatched parameters in the device handle, block these. | ||
| 813 | if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 814 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || | ||
| 815 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || | ||
| 816 | (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && | ||
| 817 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || | ||
| 818 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { | ||
| 819 | return; | ||
| 820 | } | ||
| 821 | |||
| 822 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | ||
| 823 | if (vibration_value.low_amplitude == | ||
| 824 | controller.vibration[device_index].latest_vibration_value.low_amplitude && | ||
| 825 | vibration_value.high_amplitude == | ||
| 826 | controller.vibration[device_index].latest_vibration_value.high_amplitude) { | ||
| 827 | return; | ||
| 828 | } | ||
| 829 | |||
| 830 | if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, | ||
| 831 | vibration_value)) { | ||
| 832 | controller.vibration[device_index].latest_vibration_value = vibration_value; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | void NPad::VibrateControllers( | ||
| 837 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 838 | std::span<const Core::HID::VibrationValue> vibration_values) { | ||
| 839 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 840 | return; | ||
| 841 | } | ||
| 842 | |||
| 843 | ASSERT_OR_EXECUTE_MSG( | ||
| 844 | vibration_device_handles.size() == vibration_values.size(), { return; }, | ||
| 845 | "The amount of device handles does not match with the amount of vibration values," | ||
| 846 | "this is undefined behavior!"); | ||
| 847 | |||
| 848 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 849 | VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | Core::HID::VibrationValue NPad::GetLastVibration( | ||
| 854 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 855 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 856 | return {}; | ||
| 857 | } | ||
| 858 | |||
| 859 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 860 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 861 | return controller.vibration[device_index].latest_vibration_value; | ||
| 862 | } | ||
| 863 | |||
| 864 | void NPad::InitializeVibrationDevice( | ||
| 865 | const Core::HID::VibrationDeviceHandle& vibration_device_handle) { | ||
| 866 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 867 | return; | ||
| 868 | } | ||
| 869 | |||
| 870 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 871 | const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id); | ||
| 872 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 873 | InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); | ||
| 874 | } | ||
| 875 | |||
| 876 | void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 877 | std::size_t device_index) { | ||
| 878 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 879 | if (!Settings::values.vibration_enabled.GetValue()) { | ||
| 880 | controller.vibration[device_index].device_mounted = false; | ||
| 881 | return; | ||
| 882 | } | ||
| 883 | |||
| 884 | controller.vibration[device_index].device_mounted = | ||
| 885 | controller.device->IsVibrationEnabled(device_index); | ||
| 886 | } | ||
| 887 | |||
| 888 | void NPad::SetPermitVibrationSession(bool permit_vibration_session) { | ||
| 889 | permit_vibration_session_enabled = permit_vibration_session; | ||
| 890 | } | ||
| 891 | |||
| 892 | bool NPad::IsVibrationDeviceMounted( | ||
| 893 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 894 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 895 | return false; | ||
| 896 | } | ||
| 897 | |||
| 898 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 899 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 900 | return controller.vibration[device_index].device_mounted; | ||
| 901 | } | ||
| 902 | |||
| 903 | Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | ||
| 904 | Core::HID::NpadIdType npad_id) { | ||
| 905 | std::scoped_lock lock{mutex}; | ||
| 906 | return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id); | ||
| 907 | } | ||
| 908 | |||
| 909 | void NPad::AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, | ||
| 910 | Core::HID::NpadIdType npad_id) { | ||
| 911 | UpdateControllerAt(aruid, controller, npad_id, true); | ||
| 912 | } | ||
| 913 | |||
| 914 | void NPad::UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex type, | ||
| 915 | Core::HID::NpadIdType npad_id, bool connected) { | ||
| 916 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 917 | if (!connected) { | ||
| 918 | DisconnectNpad(aruid, npad_id); | ||
| 919 | return; | ||
| 920 | } | ||
| 921 | |||
| 922 | controller.device->SetNpadStyleIndex(type); | ||
| 923 | InitNewlyAddedController(aruid, npad_id); | ||
| 924 | } | ||
| 925 | |||
| 926 | Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 927 | if (!IsNpadIdValid(npad_id)) { | ||
| 928 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 929 | return ResultInvalidNpadId; | ||
| 930 | } | ||
| 931 | |||
| 932 | LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); | ||
| 933 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 934 | for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { | ||
| 935 | // Send an empty vibration to stop any vibrations. | ||
| 936 | VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); | ||
| 937 | controller.vibration[device_idx].device_mounted = false; | ||
| 938 | } | ||
| 939 | |||
| 940 | auto* shared_memory = controller.shared_memory; | ||
| 941 | // Don't reset shared_memory->assignment_mode this value is persistent | ||
| 942 | shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out | ||
| 943 | shared_memory->device_type.raw = 0; | ||
| 944 | shared_memory->system_properties.raw = 0; | ||
| 945 | shared_memory->button_properties.raw = 0; | ||
| 946 | shared_memory->sixaxis_fullkey_properties.raw = 0; | ||
| 947 | shared_memory->sixaxis_handheld_properties.raw = 0; | ||
| 948 | shared_memory->sixaxis_dual_left_properties.raw = 0; | ||
| 949 | shared_memory->sixaxis_dual_right_properties.raw = 0; | ||
| 950 | shared_memory->sixaxis_left_properties.raw = 0; | ||
| 951 | shared_memory->sixaxis_right_properties.raw = 0; | ||
| 952 | shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty; | ||
| 953 | shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty; | ||
| 954 | shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty; | ||
| 955 | shared_memory->fullkey_color = { | ||
| 956 | .attribute = ColorAttribute::NoController, | ||
| 957 | .fullkey = {}, | ||
| 958 | }; | ||
| 959 | shared_memory->joycon_color = { | ||
| 960 | .attribute = ColorAttribute::NoController, | ||
| 961 | .left = {}, | ||
| 962 | .right = {}, | ||
| 963 | }; | ||
| 964 | shared_memory->applet_footer_type = AppletFooterUiType::None; | ||
| 965 | |||
| 966 | controller.is_dual_left_connected = true; | ||
| 967 | controller.is_dual_right_connected = true; | ||
| 968 | controller.is_connected = false; | ||
| 969 | controller.device->Disconnect(); | ||
| 970 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | ||
| 971 | WriteEmptyEntry(shared_memory); | ||
| 972 | return ResultSuccess; | ||
| 973 | } | ||
| 974 | |||
| 975 | Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor( | ||
| 976 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 977 | bool& is_firmware_available) const { | ||
| 978 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 979 | if (is_valid.IsError()) { | ||
| 980 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 981 | return is_valid; | ||
| 982 | } | ||
| 983 | |||
| 984 | const auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle); | ||
| 985 | is_firmware_available = sixaxis_properties.is_firmware_update_available != 0; | ||
| 986 | return ResultSuccess; | ||
| 987 | } | ||
| 988 | |||
| 989 | Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( | ||
| 990 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||
| 991 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 992 | if (is_valid.IsError()) { | ||
| 993 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 994 | return is_valid; | ||
| 995 | } | ||
| 996 | |||
| 997 | auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle); | ||
| 998 | sixaxis_properties.is_newly_assigned.Assign(0); | ||
| 999 | |||
| 1000 | return ResultSuccess; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 1004 | Core::HID::NpadIdType npad_id_2) { | ||
| 1005 | if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||
| 1006 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||
| 1007 | npad_id_2); | ||
| 1008 | return ResultInvalidNpadId; | ||
| 1009 | } | ||
| 1010 | auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1); | ||
| 1011 | auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2); | ||
| 1012 | auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); | ||
| 1013 | auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); | ||
| 1014 | |||
| 1015 | // Simplify this code by converting dualjoycon with only a side connected to single joycons | ||
| 1016 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 1017 | if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { | ||
| 1018 | controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft; | ||
| 1019 | } | ||
| 1020 | if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { | ||
| 1021 | controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight; | ||
| 1022 | } | ||
| 1023 | } | ||
| 1024 | if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 1025 | if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { | ||
| 1026 | controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft; | ||
| 1027 | } | ||
| 1028 | if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { | ||
| 1029 | controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight; | ||
| 1030 | } | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | // Invalid merge errors | ||
| 1034 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual || | ||
| 1035 | controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 1036 | return NpadIsDualJoycon; | ||
| 1037 | } | ||
| 1038 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 1039 | controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) { | ||
| 1040 | return NpadIsSameType; | ||
| 1041 | } | ||
| 1042 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && | ||
| 1043 | controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 1044 | return NpadIsSameType; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | // These exceptions are handled as if they where dual joycon | ||
| 1048 | if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 1049 | controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 1050 | return NpadIsDualJoycon; | ||
| 1051 | } | ||
| 1052 | if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 1053 | controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 1054 | return NpadIsDualJoycon; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | // Disconnect the joycons and connect them as dual joycon at the first index. | ||
| 1058 | DisconnectNpad(aruid, npad_id_1); | ||
| 1059 | DisconnectNpad(aruid, npad_id_2); | ||
| 1060 | controller_1.is_dual_left_connected = true; | ||
| 1061 | controller_1.is_dual_right_connected = true; | ||
| 1062 | AddNewControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); | ||
| 1063 | return ResultSuccess; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | Result NPad::StartLrAssignmentMode(u64 aruid) { | ||
| 1067 | std::scoped_lock lock{mutex}; | ||
| 1068 | bool is_enabled{}; | ||
| 1069 | Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); | ||
| 1070 | if (result.IsSuccess() && is_enabled == false) { | ||
| 1071 | result = npad_resource.SetLrAssignmentMode(aruid, true); | ||
| 1072 | } | ||
| 1073 | return result; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | Result NPad::StopLrAssignmentMode(u64 aruid) { | ||
| 1077 | std::scoped_lock lock{mutex}; | ||
| 1078 | bool is_enabled{}; | ||
| 1079 | Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); | ||
| 1080 | if (result.IsSuccess() && is_enabled == true) { | ||
| 1081 | result = npad_resource.SetLrAssignmentMode(aruid, false); | ||
| 1082 | } | ||
| 1083 | return result; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 1087 | Core::HID::NpadIdType npad_id_2) { | ||
| 1088 | if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||
| 1089 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||
| 1090 | npad_id_2); | ||
| 1091 | return ResultInvalidNpadId; | ||
| 1092 | } | ||
| 1093 | if (npad_id_1 == Core::HID::NpadIdType::Handheld || | ||
| 1094 | npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || | ||
| 1095 | npad_id_2 == Core::HID::NpadIdType::Other) { | ||
| 1096 | return ResultSuccess; | ||
| 1097 | } | ||
| 1098 | const auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1).device; | ||
| 1099 | const auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2).device; | ||
| 1100 | const auto type_index_1 = controller_1->GetNpadStyleIndex(); | ||
| 1101 | const auto type_index_2 = controller_2->GetNpadStyleIndex(); | ||
| 1102 | const auto is_connected_1 = controller_1->IsConnected(); | ||
| 1103 | const auto is_connected_2 = controller_2->IsConnected(); | ||
| 1104 | |||
| 1105 | if (!npad_resource.IsControllerSupported(aruid, type_index_1) && is_connected_1) { | ||
| 1106 | return ResultNpadNotConnected; | ||
| 1107 | } | ||
| 1108 | if (!npad_resource.IsControllerSupported(aruid, type_index_2) && is_connected_2) { | ||
| 1109 | return ResultNpadNotConnected; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | UpdateControllerAt(aruid, type_index_2, npad_id_1, is_connected_2); | ||
| 1113 | UpdateControllerAt(aruid, type_index_1, npad_id_2, is_connected_1); | ||
| 1114 | |||
| 1115 | return ResultSuccess; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const { | ||
| 1119 | if (!IsNpadIdValid(npad_id)) { | ||
| 1120 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 1121 | return ResultInvalidNpadId; | ||
| 1122 | } | ||
| 1123 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 1124 | const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device; | ||
| 1125 | pattern = controller->GetLedPattern(); | ||
| 1126 | return ResultSuccess; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | ||
| 1130 | Core::HID::NpadIdType npad_id) const { | ||
| 1131 | std::scoped_lock lock{mutex}; | ||
| 1132 | return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 1136 | bool is_enabled) { | ||
| 1137 | std::scoped_lock lock{mutex}; | ||
| 1138 | return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | void NPad::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { | ||
| 1142 | std::scoped_lock lock{mutex}; | ||
| 1143 | npad_resource.SetNpadAnalogStickUseCenterClamp(aruid, is_enabled); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | void NPad::ClearAllConnectedControllers() { | ||
| 1147 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1148 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1149 | if (controller.device->IsConnected() && | ||
| 1150 | controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { | ||
| 1151 | controller.device->Disconnect(); | ||
| 1152 | controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); | ||
| 1153 | } | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | void NPad::DisconnectAllConnectedControllers() { | ||
| 1159 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1160 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1161 | controller.device->Disconnect(); | ||
| 1162 | } | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | void NPad::ConnectAllDisconnectedControllers() { | ||
| 1167 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1168 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1169 | if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && | ||
| 1170 | !controller.device->IsConnected()) { | ||
| 1171 | controller.device->Connect(); | ||
| 1172 | } | ||
| 1173 | } | ||
| 1174 | } | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | void NPad::ClearAllControllers() { | ||
| 1178 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1179 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1180 | controller.device->Disconnect(); | ||
| 1181 | controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | Core::HID::NpadButton NPad::GetAndResetPressState() { | ||
| 1187 | return static_cast<Core::HID::NpadButton>(press_state.exchange(0)); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) { | ||
| 1191 | std::scoped_lock lock{mutex}; | ||
| 1192 | const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false); | ||
| 1193 | if (result.IsSuccess()) { | ||
| 1194 | OnUpdate({}); | ||
| 1195 | } | ||
| 1196 | return result; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) { | ||
| 1200 | std::scoped_lock lock{mutex}; | ||
| 1201 | const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true); | ||
| 1202 | if (result.IsSuccess()) { | ||
| 1203 | OnUpdate({}); | ||
| 1204 | } | ||
| 1205 | return result; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) { | ||
| 1209 | std::scoped_lock lock{mutex}; | ||
| 1210 | const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid); | ||
| 1211 | if (result.IsSuccess()) { | ||
| 1212 | OnUpdate({}); | ||
| 1213 | } | ||
| 1214 | return result; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | void NPad::SetRevision(u64 aruid, NpadRevision revision) { | ||
| 1218 | npad_resource.SetNpadRevision(aruid, revision); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | NpadRevision NPad::GetRevision(u64 aruid) { | ||
| 1222 | return npad_resource.GetNpadRevision(aruid); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | Result NPad::RegisterAppletResourceUserId(u64 aruid) { | ||
| 1226 | return npad_resource.RegisterAppletResourceUserId(aruid); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | void NPad::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 1230 | npad_resource.UnregisterAppletResourceUserId(aruid); | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, | ||
| 1234 | std::recursive_mutex* shared_mutex) { | ||
| 1235 | applet_resource_holder.applet_resource = resource; | ||
| 1236 | applet_resource_holder.shared_mutex = shared_mutex; | ||
| 1237 | applet_resource_holder.shared_npad_resource = &npad_resource; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1241 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { | ||
| 1242 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1243 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | const NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1247 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { | ||
| 1248 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1249 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1253 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) { | ||
| 1254 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1255 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | const NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1259 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const { | ||
| 1260 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1261 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(u64 aruid, | ||
| 1265 | Core::HID::NpadIdType npad_id) { | ||
| 1266 | if (!IsNpadIdValid(npad_id)) { | ||
| 1267 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 1268 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 1269 | } | ||
| 1270 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 1271 | const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); | ||
| 1272 | return controller_data[aruid_index][npad_index]; | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType( | ||
| 1276 | u64 aruid, Core::HID::NpadIdType npad_id) const { | ||
| 1277 | if (!IsNpadIdValid(npad_id)) { | ||
| 1278 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 1279 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 1280 | } | ||
| 1281 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 1282 | const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); | ||
| 1283 | return controller_data[aruid_index][npad_index]; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( | ||
| 1287 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||
| 1288 | auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); | ||
| 1289 | switch (sixaxis_handle.npad_type) { | ||
| 1290 | case Core::HID::NpadStyleIndex::ProController: | ||
| 1291 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 1292 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1293 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 1294 | return controller.shared_memory->sixaxis_handheld_properties; | ||
| 1295 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 1296 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 1297 | return controller.shared_memory->sixaxis_dual_left_properties; | ||
| 1298 | } | ||
| 1299 | return controller.shared_memory->sixaxis_dual_right_properties; | ||
| 1300 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 1301 | return controller.shared_memory->sixaxis_left_properties; | ||
| 1302 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 1303 | return controller.shared_memory->sixaxis_right_properties; | ||
| 1304 | default: | ||
| 1305 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1306 | } | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( | ||
| 1310 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | ||
| 1311 | const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); | ||
| 1312 | switch (sixaxis_handle.npad_type) { | ||
| 1313 | case Core::HID::NpadStyleIndex::ProController: | ||
| 1314 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 1315 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1316 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 1317 | return controller.shared_memory->sixaxis_handheld_properties; | ||
| 1318 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 1319 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 1320 | return controller.shared_memory->sixaxis_dual_left_properties; | ||
| 1321 | } | ||
| 1322 | return controller.shared_memory->sixaxis_dual_right_properties; | ||
| 1323 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 1324 | return controller.shared_memory->sixaxis_left_properties; | ||
| 1325 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 1326 | return controller.shared_memory->sixaxis_right_properties; | ||
| 1327 | default: | ||
| 1328 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { | ||
| 1333 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 1334 | const auto& shared_memory = GetControllerFromNpadIdType(aruid, npad_id).shared_memory; | ||
| 1335 | |||
| 1336 | return { | ||
| 1337 | .ui_variant = 0, | ||
| 1338 | .footer = shared_memory->applet_footer_type, | ||
| 1339 | }; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h deleted file mode 100644 index 8ab333064..000000000 --- a/src/core/hle/service/hid/controllers/npad.h +++ /dev/null | |||
| @@ -1,214 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <atomic> | ||
| 8 | #include <mutex> | ||
| 9 | #include <span> | ||
| 10 | |||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "core/hid/hid_types.h" | ||
| 13 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 14 | #include "core/hle/service/hid/controllers/npad/npad_resource.h" | ||
| 15 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 16 | |||
| 17 | namespace Core::HID { | ||
| 18 | class EmulatedController; | ||
| 19 | enum class ControllerTriggerType; | ||
| 20 | } // namespace Core::HID | ||
| 21 | |||
| 22 | namespace Kernel { | ||
| 23 | class KEvent; | ||
| 24 | class KReadableEvent; | ||
| 25 | } // namespace Kernel | ||
| 26 | |||
| 27 | namespace Service::KernelHelpers { | ||
| 28 | class ServiceContext; | ||
| 29 | } // namespace Service::KernelHelpers | ||
| 30 | |||
| 31 | union Result; | ||
| 32 | |||
| 33 | namespace Service::HID { | ||
| 34 | class AppletResource; | ||
| 35 | struct NpadInternalState; | ||
| 36 | struct NpadSixAxisSensorLifo; | ||
| 37 | struct NpadSharedMemoryFormat; | ||
| 38 | |||
| 39 | class NPad final { | ||
| 40 | public: | ||
| 41 | explicit NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); | ||
| 42 | ~NPad(); | ||
| 43 | |||
| 44 | Result Activate(); | ||
| 45 | Result Activate(u64 aruid); | ||
| 46 | |||
| 47 | Result ActivateNpadResource(); | ||
| 48 | Result ActivateNpadResource(u64 aruid); | ||
| 49 | |||
| 50 | // When the controller is requesting an update for the shared memory | ||
| 51 | void OnUpdate(const Core::Timing::CoreTiming& core_timing); | ||
| 52 | |||
| 53 | Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set); | ||
| 54 | Result GetSupportedNpadStyleSet(u64 aruid, | ||
| 55 | Core::HID::NpadStyleSet& out_supported_style_set) const; | ||
| 56 | Result GetMaskedSupportedNpadStyleSet(u64 aruid, | ||
| 57 | Core::HID::NpadStyleSet& out_supported_style_set) const; | ||
| 58 | |||
| 59 | Result SetSupportedNpadIdType(u64 aruid, | ||
| 60 | std::span<const Core::HID::NpadIdType> supported_npad_list); | ||
| 61 | |||
| 62 | Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); | ||
| 63 | Result GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const; | ||
| 64 | |||
| 65 | Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode); | ||
| 66 | Result GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const; | ||
| 67 | |||
| 68 | bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, | ||
| 69 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); | ||
| 70 | |||
| 71 | bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 72 | std::size_t device_index, | ||
| 73 | const Core::HID::VibrationValue& vibration_value); | ||
| 74 | |||
| 75 | void VibrateController(u64 aruid, | ||
| 76 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 77 | const Core::HID::VibrationValue& vibration_value); | ||
| 78 | |||
| 79 | void VibrateControllers( | ||
| 80 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 81 | std::span<const Core::HID::VibrationValue> vibration_values); | ||
| 82 | |||
| 83 | Core::HID::VibrationValue GetLastVibration( | ||
| 84 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 85 | |||
| 86 | void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); | ||
| 87 | |||
| 88 | void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 89 | std::size_t device_index); | ||
| 90 | |||
| 91 | void SetPermitVibrationSession(bool permit_vibration_session); | ||
| 92 | |||
| 93 | bool IsVibrationDeviceMounted( | ||
| 94 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 95 | |||
| 96 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | ||
| 97 | Core::HID::NpadIdType npad_id); | ||
| 98 | |||
| 99 | // Adds a new controller at an index. | ||
| 100 | void AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, | ||
| 101 | Core::HID::NpadIdType npad_id); | ||
| 102 | // Adds a new controller at an index with connection status. | ||
| 103 | void UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, | ||
| 104 | Core::HID::NpadIdType npad_id, bool connected); | ||
| 105 | |||
| 106 | Result DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 107 | |||
| 108 | Result IsFirmwareUpdateAvailableForSixAxisSensor( | ||
| 109 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 110 | bool& is_firmware_available) const; | ||
| 111 | Result ResetIsSixAxisSensorDeviceNewlyAssigned( | ||
| 112 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); | ||
| 113 | |||
| 114 | Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; | ||
| 115 | |||
| 116 | Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | ||
| 117 | Core::HID::NpadIdType npad_id) const; | ||
| 118 | Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 119 | bool is_enabled); | ||
| 120 | |||
| 121 | void SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); | ||
| 122 | void ClearAllConnectedControllers(); | ||
| 123 | void DisconnectAllConnectedControllers(); | ||
| 124 | void ConnectAllDisconnectedControllers(); | ||
| 125 | void ClearAllControllers(); | ||
| 126 | |||
| 127 | Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 128 | Core::HID::NpadIdType npad_id_2); | ||
| 129 | Result StartLrAssignmentMode(u64 aruid); | ||
| 130 | Result StopLrAssignmentMode(u64 aruid); | ||
| 131 | Result SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 132 | Core::HID::NpadIdType npad_id_2); | ||
| 133 | |||
| 134 | // Logical OR for all buttons presses on all controllers | ||
| 135 | // Specifically for cheat engine and other features. | ||
| 136 | Core::HID::NpadButton GetAndResetPressState(); | ||
| 137 | |||
| 138 | Result ApplyNpadSystemCommonPolicy(u64 aruid); | ||
| 139 | Result ApplyNpadSystemCommonPolicyFull(u64 aruid); | ||
| 140 | Result ClearNpadSystemCommonPolicy(u64 aruid); | ||
| 141 | |||
| 142 | void SetRevision(u64 aruid, NpadRevision revision); | ||
| 143 | NpadRevision GetRevision(u64 aruid); | ||
| 144 | |||
| 145 | Result RegisterAppletResourceUserId(u64 aruid); | ||
| 146 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 147 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, | ||
| 148 | std::recursive_mutex* shared_mutex); | ||
| 149 | |||
| 150 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); | ||
| 151 | |||
| 152 | private: | ||
| 153 | struct VibrationData { | ||
| 154 | bool device_mounted{}; | ||
| 155 | Core::HID::VibrationValue latest_vibration_value{}; | ||
| 156 | std::chrono::steady_clock::time_point last_vibration_timepoint{}; | ||
| 157 | }; | ||
| 158 | |||
| 159 | struct NpadControllerData { | ||
| 160 | NpadInternalState* shared_memory = nullptr; | ||
| 161 | Core::HID::EmulatedController* device = nullptr; | ||
| 162 | |||
| 163 | std::array<VibrationData, 2> vibration{}; | ||
| 164 | bool is_connected{}; | ||
| 165 | |||
| 166 | // Dual joycons can have only one side connected | ||
| 167 | bool is_dual_left_connected{true}; | ||
| 168 | bool is_dual_right_connected{true}; | ||
| 169 | |||
| 170 | // Current pad state | ||
| 171 | NPadGenericState npad_pad_state{}; | ||
| 172 | NPadGenericState npad_libnx_state{}; | ||
| 173 | NpadGcTriggerState npad_trigger_state{}; | ||
| 174 | int callback_key{}; | ||
| 175 | }; | ||
| 176 | |||
| 177 | void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); | ||
| 178 | void InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 179 | void RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 180 | void WriteEmptyEntry(NpadInternalState* npad); | ||
| 181 | |||
| 182 | NpadControllerData& GetControllerFromHandle( | ||
| 183 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle); | ||
| 184 | const NpadControllerData& GetControllerFromHandle( | ||
| 185 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const; | ||
| 186 | NpadControllerData& GetControllerFromHandle( | ||
| 187 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 188 | const NpadControllerData& GetControllerFromHandle( | ||
| 189 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 190 | NpadControllerData& GetControllerFromNpadIdType(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 191 | const NpadControllerData& GetControllerFromNpadIdType(u64 aruid, | ||
| 192 | Core::HID::NpadIdType npad_id) const; | ||
| 193 | |||
| 194 | Core::HID::SixAxisSensorProperties& GetSixaxisProperties( | ||
| 195 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 196 | const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( | ||
| 197 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 198 | |||
| 199 | Core::HID::HIDCore& hid_core; | ||
| 200 | KernelHelpers::ServiceContext& service_context; | ||
| 201 | |||
| 202 | s32 ref_counter{}; | ||
| 203 | mutable std::mutex mutex; | ||
| 204 | NPadResource npad_resource; | ||
| 205 | AppletResourceHolder applet_resource_holder{}; | ||
| 206 | Kernel::KEvent* input_event{nullptr}; | ||
| 207 | std::mutex* input_mutex{nullptr}; | ||
| 208 | |||
| 209 | std::atomic<u64> press_state{}; | ||
| 210 | bool permit_vibration_session_enabled; | ||
| 211 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> | ||
| 212 | controller_data{}; | ||
| 213 | }; | ||
| 214 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_data.cpp b/src/core/hle/service/hid/controllers/npad/npad_data.cpp deleted file mode 100644 index d2423b6d3..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_data.cpp +++ /dev/null | |||
| @@ -1,228 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/controllers/npad/npad_data.h" | ||
| 5 | #include "core/hle/service/hid/hid_util.h" | ||
| 6 | |||
| 7 | namespace Service::HID { | ||
| 8 | |||
| 9 | NPadData::NPadData() { | ||
| 10 | ClearNpadSystemCommonPolicy(); | ||
| 11 | } | ||
| 12 | |||
| 13 | NPadData::~NPadData() = default; | ||
| 14 | |||
| 15 | NpadStatus NPadData::GetNpadStatus() const { | ||
| 16 | return status; | ||
| 17 | } | ||
| 18 | |||
| 19 | void NPadData::SetNpadAnalogStickUseCenterClamp(bool is_enabled) { | ||
| 20 | status.use_center_clamp.Assign(is_enabled); | ||
| 21 | } | ||
| 22 | |||
| 23 | bool NPadData::GetNpadAnalogStickUseCenterClamp() const { | ||
| 24 | return status.use_center_clamp.As<bool>(); | ||
| 25 | } | ||
| 26 | |||
| 27 | void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { | ||
| 28 | status.system_ext_state.Assign(is_enabled); | ||
| 29 | } | ||
| 30 | |||
| 31 | bool NPadData::GetNpadSystemExtState() const { | ||
| 32 | return status.system_ext_state.As<bool>(); | ||
| 33 | } | ||
| 34 | |||
| 35 | Result NPadData::SetSupportedNpadIdType(std::span<const Core::HID::NpadIdType> list) { | ||
| 36 | // Note: Real limit is 11. But array size is 10. N's bug? | ||
| 37 | if (list.size() > MaxSupportedNpadIdTypes) { | ||
| 38 | return ResultInvalidArraySize; | ||
| 39 | } | ||
| 40 | |||
| 41 | supported_npad_id_types_count = list.size(); | ||
| 42 | memcpy(supported_npad_id_types.data(), list.data(), | ||
| 43 | list.size() * sizeof(Core::HID::NpadIdType)); | ||
| 44 | |||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | |||
| 48 | std::size_t NPadData::GetSupportedNpadIdType(std::span<Core::HID::NpadIdType> out_list) const { | ||
| 49 | std::size_t out_size = std::min(supported_npad_id_types_count, out_list.size()); | ||
| 50 | |||
| 51 | memcpy(out_list.data(), supported_npad_id_types.data(), | ||
| 52 | out_size * sizeof(Core::HID::NpadIdType)); | ||
| 53 | |||
| 54 | return out_size; | ||
| 55 | } | ||
| 56 | |||
| 57 | bool NPadData::IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const { | ||
| 58 | for (std::size_t i = 0; i < supported_npad_id_types_count; i++) { | ||
| 59 | if (supported_npad_id_types[i] == npad_id) { | ||
| 60 | return true; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | return false; | ||
| 65 | } | ||
| 66 | |||
| 67 | void NPadData::SetNpadSystemCommonPolicy(bool is_full_policy) { | ||
| 68 | supported_npad_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::JoyDual | | ||
| 69 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 70 | handheld_activation_mode = NpadHandheldActivationMode::Dual; | ||
| 71 | |||
| 72 | status.is_supported_styleset_set.Assign(true); | ||
| 73 | status.is_hold_type_set.Assign(true); | ||
| 74 | status.lr_assignment_mode.Assign(false); | ||
| 75 | status.is_policy.Assign(true); | ||
| 76 | if (is_full_policy) { | ||
| 77 | status.is_full_policy.Assign(true); | ||
| 78 | } | ||
| 79 | |||
| 80 | supported_npad_id_types_count = 10; | ||
| 81 | supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; | ||
| 82 | supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; | ||
| 83 | supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; | ||
| 84 | supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; | ||
| 85 | supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; | ||
| 86 | supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; | ||
| 87 | supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; | ||
| 88 | supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; | ||
| 89 | supported_npad_id_types[8] = Core::HID::NpadIdType::Other; | ||
| 90 | supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; | ||
| 91 | |||
| 92 | for (auto& input_protection : is_unintended_home_button_input_protection) { | ||
| 93 | input_protection = true; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | void NPadData::ClearNpadSystemCommonPolicy() { | ||
| 98 | status.raw = 0; | ||
| 99 | supported_npad_style_set = Core::HID::NpadStyleSet::All; | ||
| 100 | npad_hold_type = NpadJoyHoldType::Vertical; | ||
| 101 | handheld_activation_mode = NpadHandheldActivationMode::Dual; | ||
| 102 | |||
| 103 | for (auto& button_assignment : npad_button_assignment) { | ||
| 104 | button_assignment = Core::HID::NpadButton::None; | ||
| 105 | } | ||
| 106 | |||
| 107 | supported_npad_id_types_count = 10; | ||
| 108 | supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; | ||
| 109 | supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; | ||
| 110 | supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; | ||
| 111 | supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; | ||
| 112 | supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; | ||
| 113 | supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; | ||
| 114 | supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; | ||
| 115 | supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; | ||
| 116 | supported_npad_id_types[8] = Core::HID::NpadIdType::Other; | ||
| 117 | supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; | ||
| 118 | |||
| 119 | for (auto& input_protection : is_unintended_home_button_input_protection) { | ||
| 120 | input_protection = true; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | void NPadData::SetNpadJoyHoldType(NpadJoyHoldType hold_type) { | ||
| 125 | npad_hold_type = hold_type; | ||
| 126 | status.is_hold_type_set.Assign(true); | ||
| 127 | } | ||
| 128 | |||
| 129 | NpadJoyHoldType NPadData::GetNpadJoyHoldType() const { | ||
| 130 | return npad_hold_type; | ||
| 131 | } | ||
| 132 | |||
| 133 | void NPadData::SetHandheldActivationMode(NpadHandheldActivationMode activation_mode) { | ||
| 134 | handheld_activation_mode = activation_mode; | ||
| 135 | } | ||
| 136 | |||
| 137 | NpadHandheldActivationMode NPadData::GetHandheldActivationMode() const { | ||
| 138 | return handheld_activation_mode; | ||
| 139 | } | ||
| 140 | |||
| 141 | void NPadData::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set) { | ||
| 142 | supported_npad_style_set = style_set; | ||
| 143 | status.is_supported_styleset_set.Assign(true); | ||
| 144 | status.is_hold_type_set.Assign(true); | ||
| 145 | } | ||
| 146 | |||
| 147 | Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const { | ||
| 148 | return supported_npad_style_set; | ||
| 149 | } | ||
| 150 | |||
| 151 | bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { | ||
| 152 | Core::HID::NpadStyleTag style = {supported_npad_style_set}; | ||
| 153 | switch (style_index) { | ||
| 154 | case Core::HID::NpadStyleIndex::ProController: | ||
| 155 | return style.fullkey.As<bool>(); | ||
| 156 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 157 | return style.handheld.As<bool>(); | ||
| 158 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 159 | return style.joycon_dual.As<bool>(); | ||
| 160 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 161 | return style.joycon_left.As<bool>(); | ||
| 162 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 163 | return style.joycon_right.As<bool>(); | ||
| 164 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 165 | return style.gamecube.As<bool>(); | ||
| 166 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 167 | return style.palma.As<bool>(); | ||
| 168 | case Core::HID::NpadStyleIndex::NES: | ||
| 169 | return style.lark.As<bool>(); | ||
| 170 | case Core::HID::NpadStyleIndex::SNES: | ||
| 171 | return style.lucia.As<bool>(); | ||
| 172 | case Core::HID::NpadStyleIndex::N64: | ||
| 173 | return style.lagoon.As<bool>(); | ||
| 174 | case Core::HID::NpadStyleIndex::SegaGenesis: | ||
| 175 | return style.lager.As<bool>(); | ||
| 176 | default: | ||
| 177 | return false; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | void NPadData::SetLrAssignmentMode(bool is_enabled) { | ||
| 182 | status.lr_assignment_mode.Assign(is_enabled); | ||
| 183 | } | ||
| 184 | |||
| 185 | bool NPadData::GetLrAssignmentMode() const { | ||
| 186 | return status.lr_assignment_mode.As<bool>(); | ||
| 187 | } | ||
| 188 | |||
| 189 | void NPadData::SetAssigningSingleOnSlSrPress(bool is_enabled) { | ||
| 190 | status.assigning_single_on_sl_sr_press.Assign(is_enabled); | ||
| 191 | } | ||
| 192 | |||
| 193 | bool NPadData::GetAssigningSingleOnSlSrPress() const { | ||
| 194 | return status.assigning_single_on_sl_sr_press.As<bool>(); | ||
| 195 | } | ||
| 196 | |||
| 197 | void NPadData::SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id) { | ||
| 198 | is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)] = is_enabled; | ||
| 199 | } | ||
| 200 | |||
| 201 | bool NPadData::GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const { | ||
| 202 | return is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)]; | ||
| 203 | } | ||
| 204 | |||
| 205 | void NPadData::SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, | ||
| 206 | std::size_t style_index) { | ||
| 207 | npad_button_assignment[style_index] = button_assignment; | ||
| 208 | } | ||
| 209 | |||
| 210 | Core::HID::NpadButton NPadData::GetCaptureButtonAssignment(std::size_t style_index) const { | ||
| 211 | return npad_button_assignment[style_index]; | ||
| 212 | } | ||
| 213 | |||
| 214 | std::size_t NPadData::GetNpadCaptureButtonAssignmentList( | ||
| 215 | std::span<Core::HID::NpadButton> out_list) const { | ||
| 216 | for (std::size_t i = 0; i < out_list.size(); i++) { | ||
| 217 | Core::HID::NpadStyleSet style_set = GetStylesetByIndex(i); | ||
| 218 | if ((style_set & supported_npad_style_set) == Core::HID::NpadStyleSet::None || | ||
| 219 | npad_button_assignment[i] == Core::HID::NpadButton::None) { | ||
| 220 | return i; | ||
| 221 | } | ||
| 222 | out_list[i] = npad_button_assignment[i]; | ||
| 223 | } | ||
| 224 | |||
| 225 | return out_list.size(); | ||
| 226 | } | ||
| 227 | |||
| 228 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_data.h b/src/core/hle/service/hid/controllers/npad/npad_data.h deleted file mode 100644 index f799a9f9c..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_data.h +++ /dev/null | |||
| @@ -1,88 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hid/hid_types.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | |||
| 16 | struct NpadStatus { | ||
| 17 | union { | ||
| 18 | u32 raw{}; | ||
| 19 | |||
| 20 | BitField<0, 1, u32> is_supported_styleset_set; | ||
| 21 | BitField<1, 1, u32> is_hold_type_set; | ||
| 22 | BitField<2, 1, u32> lr_assignment_mode; | ||
| 23 | BitField<3, 1, u32> assigning_single_on_sl_sr_press; | ||
| 24 | BitField<4, 1, u32> is_full_policy; | ||
| 25 | BitField<5, 1, u32> is_policy; | ||
| 26 | BitField<6, 1, u32> use_center_clamp; | ||
| 27 | BitField<7, 1, u32> system_ext_state; | ||
| 28 | }; | ||
| 29 | }; | ||
| 30 | static_assert(sizeof(NpadStatus) == 4, "NpadStatus is an invalid size"); | ||
| 31 | |||
| 32 | /// Handles Npad request from HID interfaces | ||
| 33 | class NPadData final { | ||
| 34 | public: | ||
| 35 | explicit NPadData(); | ||
| 36 | ~NPadData(); | ||
| 37 | |||
| 38 | NpadStatus GetNpadStatus() const; | ||
| 39 | |||
| 40 | void SetNpadAnalogStickUseCenterClamp(bool is_enabled); | ||
| 41 | bool GetNpadAnalogStickUseCenterClamp() const; | ||
| 42 | |||
| 43 | void SetNpadSystemExtStateEnabled(bool is_enabled); | ||
| 44 | bool GetNpadSystemExtState() const; | ||
| 45 | |||
| 46 | Result SetSupportedNpadIdType(std::span<const Core::HID::NpadIdType> list); | ||
| 47 | std::size_t GetSupportedNpadIdType(std::span<Core::HID::NpadIdType> out_list) const; | ||
| 48 | bool IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const; | ||
| 49 | |||
| 50 | void SetNpadSystemCommonPolicy(bool is_full_policy); | ||
| 51 | void ClearNpadSystemCommonPolicy(); | ||
| 52 | |||
| 53 | void SetNpadJoyHoldType(NpadJoyHoldType hold_type); | ||
| 54 | NpadJoyHoldType GetNpadJoyHoldType() const; | ||
| 55 | |||
| 56 | void SetHandheldActivationMode(NpadHandheldActivationMode activation_mode); | ||
| 57 | NpadHandheldActivationMode GetHandheldActivationMode() const; | ||
| 58 | |||
| 59 | void SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set); | ||
| 60 | Core::HID::NpadStyleSet GetSupportedNpadStyleSet() const; | ||
| 61 | bool IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const; | ||
| 62 | |||
| 63 | void SetLrAssignmentMode(bool is_enabled); | ||
| 64 | bool GetLrAssignmentMode() const; | ||
| 65 | |||
| 66 | void SetAssigningSingleOnSlSrPress(bool is_enabled); | ||
| 67 | bool GetAssigningSingleOnSlSrPress() const; | ||
| 68 | |||
| 69 | void SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id); | ||
| 70 | bool GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const; | ||
| 71 | |||
| 72 | void SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, | ||
| 73 | std::size_t style_index); | ||
| 74 | Core::HID::NpadButton GetCaptureButtonAssignment(std::size_t style_index) const; | ||
| 75 | std::size_t GetNpadCaptureButtonAssignmentList(std::span<Core::HID::NpadButton> out_list) const; | ||
| 76 | |||
| 77 | private: | ||
| 78 | NpadStatus status{}; | ||
| 79 | Core::HID::NpadStyleSet supported_npad_style_set{Core::HID::NpadStyleSet::All}; | ||
| 80 | NpadJoyHoldType npad_hold_type{NpadJoyHoldType::Vertical}; | ||
| 81 | NpadHandheldActivationMode handheld_activation_mode{}; | ||
| 82 | std::array<Core::HID::NpadIdType, MaxSupportedNpadIdTypes> supported_npad_id_types{}; | ||
| 83 | std::array<Core::HID::NpadButton, StyleIndexCount> npad_button_assignment{}; | ||
| 84 | std::size_t supported_npad_id_types_count{}; | ||
| 85 | std::array<bool, MaxSupportedNpadIdTypes> is_unintended_home_button_input_protection{}; | ||
| 86 | }; | ||
| 87 | |||
| 88 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_resource.cpp b/src/core/hle/service/hid/controllers/npad/npad_resource.cpp deleted file mode 100644 index 0a9341a39..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_resource.cpp +++ /dev/null | |||
| @@ -1,685 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 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 "core/hle/service/hid/controllers/npad/npad_resource.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 8 | #include "core/hle/service/hid/errors.h" | ||
| 9 | #include "core/hle/service/hid/hid_util.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | |||
| 13 | NPadResource::NPadResource(KernelHelpers::ServiceContext& context) : service_context{context} {} | ||
| 14 | |||
| 15 | NPadResource::~NPadResource() = default; | ||
| 16 | |||
| 17 | Result NPadResource::RegisterAppletResourceUserId(u64 aruid) { | ||
| 18 | const auto aruid_index = GetIndexFromAruid(aruid); | ||
| 19 | if (aruid_index < AruidIndexMax) { | ||
| 20 | return ResultAruidAlreadyRegistered; | ||
| 21 | } | ||
| 22 | |||
| 23 | std::size_t data_index = AruidIndexMax; | ||
| 24 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 25 | if (!state[i].flag.is_initialized) { | ||
| 26 | data_index = i; | ||
| 27 | break; | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | if (data_index == AruidIndexMax) { | ||
| 32 | return ResultAruidNoAvailableEntries; | ||
| 33 | } | ||
| 34 | |||
| 35 | auto& aruid_data = state[data_index]; | ||
| 36 | |||
| 37 | aruid_data.aruid = aruid; | ||
| 38 | aruid_data.flag.is_initialized.Assign(true); | ||
| 39 | |||
| 40 | data_index = AruidIndexMax; | ||
| 41 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 42 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 43 | if (registration_list.aruid[i] != aruid) { | ||
| 44 | continue; | ||
| 45 | } | ||
| 46 | data_index = i; | ||
| 47 | break; | ||
| 48 | } | ||
| 49 | if (registration_list.flag[i] == RegistrationStatus::None) { | ||
| 50 | data_index = i; | ||
| 51 | break; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | if (data_index == AruidIndexMax) { | ||
| 56 | return ResultSuccess; | ||
| 57 | } | ||
| 58 | |||
| 59 | registration_list.flag[data_index] = RegistrationStatus::Initialized; | ||
| 60 | registration_list.aruid[data_index] = aruid; | ||
| 61 | |||
| 62 | return ResultSuccess; | ||
| 63 | } | ||
| 64 | |||
| 65 | void NPadResource::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 66 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 67 | |||
| 68 | DestroyStyleSetUpdateEvents(aruid); | ||
| 69 | if (aruid_index < AruidIndexMax) { | ||
| 70 | state[aruid_index] = {}; | ||
| 71 | registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | void NPadResource::DestroyStyleSetUpdateEvents(u64 aruid) { | ||
| 76 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 77 | |||
| 78 | if (aruid_index >= AruidIndexMax) { | ||
| 79 | return; | ||
| 80 | } | ||
| 81 | |||
| 82 | for (auto& controller_state : state[aruid_index].controller_state) { | ||
| 83 | if (!controller_state.is_styleset_update_event_initialized) { | ||
| 84 | continue; | ||
| 85 | } | ||
| 86 | service_context.CloseEvent(controller_state.style_set_update_event); | ||
| 87 | controller_state.is_styleset_update_event_initialized = false; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | Result NPadResource::Activate(u64 aruid) { | ||
| 92 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 93 | |||
| 94 | if (aruid_index >= AruidIndexMax) { | ||
| 95 | return ResultSuccess; | ||
| 96 | } | ||
| 97 | |||
| 98 | auto& state_data = state[aruid_index]; | ||
| 99 | |||
| 100 | if (state_data.flag.is_assigned) { | ||
| 101 | return ResultAruidAlreadyRegistered; | ||
| 102 | } | ||
| 103 | |||
| 104 | state_data.flag.is_assigned.Assign(true); | ||
| 105 | state_data.data.ClearNpadSystemCommonPolicy(); | ||
| 106 | state_data.npad_revision = NpadRevision::Revision0; | ||
| 107 | state_data.button_config = {}; | ||
| 108 | |||
| 109 | if (active_data_aruid == aruid) { | ||
| 110 | default_hold_type = active_data.GetNpadJoyHoldType(); | ||
| 111 | active_data.SetNpadJoyHoldType(default_hold_type); | ||
| 112 | } | ||
| 113 | return ResultSuccess; | ||
| 114 | } | ||
| 115 | |||
| 116 | Result NPadResource::Activate() { | ||
| 117 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 118 | return ResultAppletResourceOverflow; | ||
| 119 | } | ||
| 120 | if (ref_counter == 0) { | ||
| 121 | RegisterAppletResourceUserId(SystemAruid); | ||
| 122 | Activate(SystemAruid); | ||
| 123 | } | ||
| 124 | ref_counter++; | ||
| 125 | return ResultSuccess; | ||
| 126 | } | ||
| 127 | |||
| 128 | Result NPadResource::Deactivate() { | ||
| 129 | if (ref_counter == 0) { | ||
| 130 | return ResultAppletResourceNotInitialized; | ||
| 131 | } | ||
| 132 | |||
| 133 | UnregisterAppletResourceUserId(SystemAruid); | ||
| 134 | ref_counter--; | ||
| 135 | return ResultSuccess; | ||
| 136 | } | ||
| 137 | |||
| 138 | NPadData* NPadResource::GetActiveData() { | ||
| 139 | return &active_data; | ||
| 140 | } | ||
| 141 | |||
| 142 | u64 NPadResource::GetActiveDataAruid() { | ||
| 143 | return active_data_aruid; | ||
| 144 | } | ||
| 145 | |||
| 146 | void NPadResource::SetAppletResourceUserId(u64 aruid) { | ||
| 147 | if (active_data_aruid == aruid) { | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | |||
| 151 | active_data_aruid = aruid; | ||
| 152 | default_hold_type = active_data.GetNpadJoyHoldType(); | ||
| 153 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 154 | |||
| 155 | if (aruid_index >= AruidIndexMax) { | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | |||
| 159 | auto& data = state[aruid_index].data; | ||
| 160 | if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { | ||
| 161 | data.SetNpadJoyHoldType(default_hold_type); | ||
| 162 | } | ||
| 163 | |||
| 164 | active_data = data; | ||
| 165 | if (data.GetNpadStatus().is_hold_type_set) { | ||
| 166 | active_data.SetNpadJoyHoldType(default_hold_type); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | std::size_t NPadResource::GetIndexFromAruid(u64 aruid) const { | ||
| 171 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 172 | if (registration_list.flag[i] == RegistrationStatus::Initialized && | ||
| 173 | registration_list.aruid[i] == aruid) { | ||
| 174 | return i; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | return AruidIndexMax; | ||
| 178 | } | ||
| 179 | |||
| 180 | Result NPadResource::ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy) { | ||
| 181 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 182 | if (aruid_index >= AruidIndexMax) { | ||
| 183 | return ResultNpadNotConnected; | ||
| 184 | } | ||
| 185 | |||
| 186 | auto& data = state[aruid_index].data; | ||
| 187 | data.SetNpadSystemCommonPolicy(is_full_policy); | ||
| 188 | data.SetNpadJoyHoldType(default_hold_type); | ||
| 189 | if (active_data_aruid == aruid) { | ||
| 190 | active_data.SetNpadSystemCommonPolicy(is_full_policy); | ||
| 191 | active_data.SetNpadJoyHoldType(default_hold_type); | ||
| 192 | } | ||
| 193 | return ResultSuccess; | ||
| 194 | } | ||
| 195 | |||
| 196 | Result NPadResource::ClearNpadSystemCommonPolicy(u64 aruid) { | ||
| 197 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 198 | if (aruid_index >= AruidIndexMax) { | ||
| 199 | return ResultNpadNotConnected; | ||
| 200 | } | ||
| 201 | |||
| 202 | state[aruid_index].data.ClearNpadSystemCommonPolicy(); | ||
| 203 | if (active_data_aruid == aruid) { | ||
| 204 | active_data.ClearNpadSystemCommonPolicy(); | ||
| 205 | } | ||
| 206 | return ResultSuccess; | ||
| 207 | } | ||
| 208 | |||
| 209 | Result NPadResource::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set) { | ||
| 210 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 211 | if (aruid_index >= AruidIndexMax) { | ||
| 212 | return ResultNpadNotConnected; | ||
| 213 | } | ||
| 214 | |||
| 215 | auto& data = state[aruid_index].data; | ||
| 216 | data.SetSupportedNpadStyleSet(style_set); | ||
| 217 | if (active_data_aruid == aruid) { | ||
| 218 | active_data.SetSupportedNpadStyleSet(style_set); | ||
| 219 | active_data.SetNpadJoyHoldType(data.GetNpadJoyHoldType()); | ||
| 220 | } | ||
| 221 | return ResultSuccess; | ||
| 222 | } | ||
| 223 | |||
| 224 | Result NPadResource::GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, | ||
| 225 | u64 aruid) const { | ||
| 226 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 227 | if (aruid_index >= AruidIndexMax) { | ||
| 228 | return ResultNpadNotConnected; | ||
| 229 | } | ||
| 230 | |||
| 231 | auto& data = state[aruid_index].data; | ||
| 232 | if (!data.GetNpadStatus().is_supported_styleset_set) { | ||
| 233 | return ResultUndefinedStyleset; | ||
| 234 | } | ||
| 235 | |||
| 236 | out_style_Set = data.GetSupportedNpadStyleSet(); | ||
| 237 | return ResultSuccess; | ||
| 238 | } | ||
| 239 | |||
| 240 | Result NPadResource::GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, | ||
| 241 | u64 aruid) const { | ||
| 242 | if (aruid == SystemAruid) { | ||
| 243 | out_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 244 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 245 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Palma | | ||
| 246 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 247 | return ResultSuccess; | ||
| 248 | } | ||
| 249 | |||
| 250 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 251 | if (aruid_index >= AruidIndexMax) { | ||
| 252 | return ResultNpadNotConnected; | ||
| 253 | } | ||
| 254 | |||
| 255 | auto& data = state[aruid_index].data; | ||
| 256 | if (!data.GetNpadStatus().is_supported_styleset_set) { | ||
| 257 | return ResultUndefinedStyleset; | ||
| 258 | } | ||
| 259 | |||
| 260 | Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; | ||
| 261 | out_style_set = data.GetSupportedNpadStyleSet(); | ||
| 262 | |||
| 263 | switch (state[aruid_index].npad_revision) { | ||
| 264 | case NpadRevision::Revision1: | ||
| 265 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 266 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 267 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 268 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | | ||
| 269 | Core::HID::NpadStyleSet::System; | ||
| 270 | break; | ||
| 271 | case NpadRevision::Revision2: | ||
| 272 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 273 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 274 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 275 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 276 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 277 | break; | ||
| 278 | case NpadRevision::Revision3: | ||
| 279 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 280 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 281 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 282 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 283 | Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | | ||
| 284 | Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | | ||
| 285 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 286 | break; | ||
| 287 | default: | ||
| 288 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 289 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 290 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | | ||
| 291 | Core::HID::NpadStyleSet::System; | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | out_style_set = out_style_set & mask; | ||
| 296 | return ResultSuccess; | ||
| 297 | } | ||
| 298 | |||
| 299 | Result NPadResource::GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const { | ||
| 300 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 301 | if (aruid_index >= AruidIndexMax) { | ||
| 302 | return ResultNpadNotConnected; | ||
| 303 | } | ||
| 304 | |||
| 305 | auto& data = state[aruid_index].data; | ||
| 306 | if (!data.GetNpadStatus().is_supported_styleset_set) { | ||
| 307 | return ResultUndefinedStyleset; | ||
| 308 | } | ||
| 309 | |||
| 310 | Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; | ||
| 311 | out_style_set = data.GetSupportedNpadStyleSet(); | ||
| 312 | |||
| 313 | switch (state[aruid_index].npad_revision) { | ||
| 314 | case NpadRevision::Revision1: | ||
| 315 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 316 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 317 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 318 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | | ||
| 319 | Core::HID::NpadStyleSet::System; | ||
| 320 | break; | ||
| 321 | case NpadRevision::Revision2: | ||
| 322 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 323 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 324 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 325 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 326 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 327 | break; | ||
| 328 | case NpadRevision::Revision3: | ||
| 329 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 330 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 331 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 332 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 333 | Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | | ||
| 334 | Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | | ||
| 335 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 336 | break; | ||
| 337 | default: | ||
| 338 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 339 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 340 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | | ||
| 341 | Core::HID::NpadStyleSet::System; | ||
| 342 | break; | ||
| 343 | } | ||
| 344 | |||
| 345 | out_style_set = out_style_set & mask; | ||
| 346 | return ResultSuccess; | ||
| 347 | } | ||
| 348 | |||
| 349 | NpadRevision NPadResource::GetNpadRevision(u64 aruid) const { | ||
| 350 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 351 | if (aruid_index >= AruidIndexMax) { | ||
| 352 | return NpadRevision::Revision0; | ||
| 353 | } | ||
| 354 | |||
| 355 | return state[aruid_index].npad_revision; | ||
| 356 | } | ||
| 357 | |||
| 358 | Result NPadResource::IsSupportedNpadStyleSet(bool& is_set, u64 aruid) { | ||
| 359 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 360 | if (aruid_index >= AruidIndexMax) { | ||
| 361 | return ResultNpadNotConnected; | ||
| 362 | } | ||
| 363 | |||
| 364 | is_set = state[aruid_index].data.GetNpadStatus().is_supported_styleset_set.Value() != 0; | ||
| 365 | return ResultSuccess; | ||
| 366 | } | ||
| 367 | |||
| 368 | Result NPadResource::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { | ||
| 369 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 370 | if (aruid_index >= AruidIndexMax) { | ||
| 371 | return ResultNpadNotConnected; | ||
| 372 | } | ||
| 373 | |||
| 374 | state[aruid_index].data.SetNpadJoyHoldType(hold_type); | ||
| 375 | if (active_data_aruid == aruid) { | ||
| 376 | active_data.SetNpadJoyHoldType(hold_type); | ||
| 377 | } | ||
| 378 | return ResultSuccess; | ||
| 379 | } | ||
| 380 | |||
| 381 | Result NPadResource::GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const { | ||
| 382 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 383 | if (aruid_index >= AruidIndexMax) { | ||
| 384 | return ResultNpadNotConnected; | ||
| 385 | } | ||
| 386 | |||
| 387 | auto& data = state[aruid_index].data; | ||
| 388 | if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { | ||
| 389 | hold_type = active_data.GetNpadJoyHoldType(); | ||
| 390 | return ResultSuccess; | ||
| 391 | } | ||
| 392 | hold_type = data.GetNpadJoyHoldType(); | ||
| 393 | return ResultSuccess; | ||
| 394 | } | ||
| 395 | |||
| 396 | Result NPadResource::SetNpadHandheldActivationMode(u64 aruid, | ||
| 397 | NpadHandheldActivationMode activation_mode) { | ||
| 398 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 399 | if (aruid_index >= AruidIndexMax) { | ||
| 400 | return ResultNpadNotConnected; | ||
| 401 | } | ||
| 402 | |||
| 403 | state[aruid_index].data.SetHandheldActivationMode(activation_mode); | ||
| 404 | if (active_data_aruid == aruid) { | ||
| 405 | active_data.SetHandheldActivationMode(activation_mode); | ||
| 406 | } | ||
| 407 | return ResultSuccess; | ||
| 408 | } | ||
| 409 | |||
| 410 | Result NPadResource::GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, | ||
| 411 | u64 aruid) const { | ||
| 412 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 413 | if (aruid_index >= AruidIndexMax) { | ||
| 414 | return ResultNpadNotConnected; | ||
| 415 | } | ||
| 416 | |||
| 417 | activation_mode = state[aruid_index].data.GetHandheldActivationMode(); | ||
| 418 | return ResultSuccess; | ||
| 419 | } | ||
| 420 | |||
| 421 | Result NPadResource::SetSupportedNpadIdType( | ||
| 422 | u64 aruid, std::span<const Core::HID::NpadIdType> supported_npad_list) { | ||
| 423 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 424 | if (aruid_index >= AruidIndexMax) { | ||
| 425 | return ResultNpadNotConnected; | ||
| 426 | } | ||
| 427 | if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { | ||
| 428 | return ResultInvalidArraySize; | ||
| 429 | } | ||
| 430 | |||
| 431 | Result result = state[aruid_index].data.SetSupportedNpadIdType(supported_npad_list); | ||
| 432 | if (result.IsSuccess() && active_data_aruid == aruid) { | ||
| 433 | result = active_data.SetSupportedNpadIdType(supported_npad_list); | ||
| 434 | } | ||
| 435 | |||
| 436 | return result; | ||
| 437 | } | ||
| 438 | |||
| 439 | bool NPadResource::IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const { | ||
| 440 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 441 | if (aruid_index >= AruidIndexMax) { | ||
| 442 | return false; | ||
| 443 | } | ||
| 444 | return state[aruid_index].data.IsNpadStyleIndexSupported(style_index); | ||
| 445 | } | ||
| 446 | |||
| 447 | Result NPadResource::SetLrAssignmentMode(u64 aruid, bool is_enabled) { | ||
| 448 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 449 | if (aruid_index >= AruidIndexMax) { | ||
| 450 | return ResultNpadNotConnected; | ||
| 451 | } | ||
| 452 | |||
| 453 | state[aruid_index].data.SetLrAssignmentMode(is_enabled); | ||
| 454 | if (active_data_aruid == aruid) { | ||
| 455 | active_data.SetLrAssignmentMode(is_enabled); | ||
| 456 | } | ||
| 457 | return ResultSuccess; | ||
| 458 | } | ||
| 459 | |||
| 460 | Result NPadResource::GetLrAssignmentMode(bool& is_enabled, u64 aruid) const { | ||
| 461 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 462 | if (aruid_index >= AruidIndexMax) { | ||
| 463 | return ResultNpadNotConnected; | ||
| 464 | } | ||
| 465 | |||
| 466 | is_enabled = state[aruid_index].data.GetLrAssignmentMode(); | ||
| 467 | return ResultSuccess; | ||
| 468 | } | ||
| 469 | |||
| 470 | Result NPadResource::SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) { | ||
| 471 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 472 | if (aruid_index >= AruidIndexMax) { | ||
| 473 | return ResultNpadNotConnected; | ||
| 474 | } | ||
| 475 | |||
| 476 | state[aruid_index].data.SetAssigningSingleOnSlSrPress(is_enabled); | ||
| 477 | if (active_data_aruid == aruid) { | ||
| 478 | active_data.SetAssigningSingleOnSlSrPress(is_enabled); | ||
| 479 | } | ||
| 480 | return ResultSuccess; | ||
| 481 | } | ||
| 482 | |||
| 483 | Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const { | ||
| 484 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 485 | if (aruid_index >= AruidIndexMax) { | ||
| 486 | return ResultNpadNotConnected; | ||
| 487 | } | ||
| 488 | |||
| 489 | is_enabled = state[aruid_index].data.GetAssigningSingleOnSlSrPress(); | ||
| 490 | return ResultSuccess; | ||
| 491 | } | ||
| 492 | |||
| 493 | Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, | ||
| 494 | Kernel::KReadableEvent** out_event, | ||
| 495 | Core::HID::NpadIdType npad_id) { | ||
| 496 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 497 | if (aruid_index >= AruidIndexMax) { | ||
| 498 | return ResultNpadNotConnected; | ||
| 499 | } | ||
| 500 | |||
| 501 | auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; | ||
| 502 | if (!controller_state.is_styleset_update_event_initialized) { | ||
| 503 | // Auto clear = true | ||
| 504 | controller_state.style_set_update_event = | ||
| 505 | service_context.CreateEvent("NpadResource:StylesetUpdateEvent"); | ||
| 506 | |||
| 507 | // Assume creating the event succeeds otherwise crash the system here | ||
| 508 | controller_state.is_styleset_update_event_initialized = true; | ||
| 509 | } | ||
| 510 | |||
| 511 | *out_event = &controller_state.style_set_update_event->GetReadableEvent(); | ||
| 512 | |||
| 513 | if (controller_state.is_styleset_update_event_initialized) { | ||
| 514 | controller_state.style_set_update_event->Signal(); | ||
| 515 | } | ||
| 516 | |||
| 517 | return ResultSuccess; | ||
| 518 | } | ||
| 519 | |||
| 520 | Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 521 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 522 | if (aruid_index >= AruidIndexMax) { | ||
| 523 | return ResultNpadNotConnected; | ||
| 524 | } | ||
| 525 | auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; | ||
| 526 | if (controller.is_styleset_update_event_initialized) { | ||
| 527 | controller.style_set_update_event->Signal(); | ||
| 528 | } | ||
| 529 | return ResultSuccess; | ||
| 530 | } | ||
| 531 | |||
| 532 | Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, | ||
| 533 | Core::HID::NpadIdType npad_id) const { | ||
| 534 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 535 | if (aruid_index >= AruidIndexMax) { | ||
| 536 | return ResultNpadNotConnected; | ||
| 537 | } | ||
| 538 | |||
| 539 | is_enabled = state[aruid_index].data.GetHomeProtectionEnabled(npad_id); | ||
| 540 | return ResultSuccess; | ||
| 541 | } | ||
| 542 | |||
| 543 | Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 544 | bool is_enabled) { | ||
| 545 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 546 | if (aruid_index >= AruidIndexMax) { | ||
| 547 | return ResultNpadNotConnected; | ||
| 548 | } | ||
| 549 | |||
| 550 | state[aruid_index].data.SetHomeProtectionEnabled(is_enabled, npad_id); | ||
| 551 | if (active_data_aruid == aruid) { | ||
| 552 | active_data.SetHomeProtectionEnabled(is_enabled, npad_id); | ||
| 553 | } | ||
| 554 | return ResultSuccess; | ||
| 555 | } | ||
| 556 | |||
| 557 | Result NPadResource::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { | ||
| 558 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 559 | if (aruid_index >= AruidIndexMax) { | ||
| 560 | return ResultNpadNotConnected; | ||
| 561 | } | ||
| 562 | |||
| 563 | state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 564 | if (active_data_aruid == aruid) { | ||
| 565 | active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 566 | } | ||
| 567 | return ResultSuccess; | ||
| 568 | } | ||
| 569 | |||
| 570 | Result NPadResource::SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, | ||
| 571 | Core::HID::NpadButton button_config) { | ||
| 572 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 573 | if (aruid_index >= AruidIndexMax) { | ||
| 574 | return ResultNpadNotConnected; | ||
| 575 | } | ||
| 576 | |||
| 577 | state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index] = button_config; | ||
| 578 | return ResultSuccess; | ||
| 579 | } | ||
| 580 | |||
| 581 | Core::HID::NpadButton NPadResource::GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 582 | std::size_t index, Core::HID::NpadButton mask, | ||
| 583 | bool is_enabled) { | ||
| 584 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 585 | if (aruid_index >= AruidIndexMax) { | ||
| 586 | return Core::HID::NpadButton::None; | ||
| 587 | } | ||
| 588 | |||
| 589 | auto& button_config = state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index]; | ||
| 590 | if (is_enabled) { | ||
| 591 | button_config = button_config | mask; | ||
| 592 | return button_config; | ||
| 593 | } | ||
| 594 | |||
| 595 | button_config = Core::HID::NpadButton::None; | ||
| 596 | return Core::HID::NpadButton::None; | ||
| 597 | } | ||
| 598 | |||
| 599 | void NPadResource::ResetButtonConfig() { | ||
| 600 | for (auto& selected_state : state) { | ||
| 601 | selected_state.button_config = {}; | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | Result NPadResource::SetNpadCaptureButtonAssignment(u64 aruid, | ||
| 606 | Core::HID::NpadStyleSet npad_style_set, | ||
| 607 | Core::HID::NpadButton button_assignment) { | ||
| 608 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 609 | if (aruid_index >= AruidIndexMax) { | ||
| 610 | return ResultNpadNotConnected; | ||
| 611 | } | ||
| 612 | |||
| 613 | // Must be a power of two | ||
| 614 | const auto raw_styleset = static_cast<u32>(npad_style_set); | ||
| 615 | if (raw_styleset == 0 && (raw_styleset & (raw_styleset - 1)) != 0) { | ||
| 616 | return ResultMultipleStyleSetSelected; | ||
| 617 | } | ||
| 618 | |||
| 619 | std::size_t style_index{}; | ||
| 620 | Core::HID::NpadStyleSet style_selected{}; | ||
| 621 | for (style_index = 0; style_index < StyleIndexCount; ++style_index) { | ||
| 622 | style_selected = GetStylesetByIndex(style_index); | ||
| 623 | if (npad_style_set == style_selected) { | ||
| 624 | break; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 628 | if (style_selected == Core::HID::NpadStyleSet::None) { | ||
| 629 | return ResultMultipleStyleSetSelected; | ||
| 630 | } | ||
| 631 | |||
| 632 | state[aruid_index].data.SetCaptureButtonAssignment(button_assignment, style_index); | ||
| 633 | if (active_data_aruid == aruid) { | ||
| 634 | active_data.SetCaptureButtonAssignment(button_assignment, style_index); | ||
| 635 | } | ||
| 636 | return ResultSuccess; | ||
| 637 | } | ||
| 638 | |||
| 639 | Result NPadResource::ClearNpadCaptureButtonAssignment(u64 aruid) { | ||
| 640 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 641 | if (aruid_index >= AruidIndexMax) { | ||
| 642 | return ResultNpadNotConnected; | ||
| 643 | } | ||
| 644 | |||
| 645 | for (std::size_t i = 0; i < StyleIndexCount; i++) { | ||
| 646 | state[aruid_index].data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); | ||
| 647 | if (active_data_aruid == aruid) { | ||
| 648 | active_data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); | ||
| 649 | } | ||
| 650 | } | ||
| 651 | return ResultSuccess; | ||
| 652 | } | ||
| 653 | |||
| 654 | std::size_t NPadResource::GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list, | ||
| 655 | u64 aruid) const { | ||
| 656 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 657 | if (aruid_index >= AruidIndexMax) { | ||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | return state[aruid_index].data.GetNpadCaptureButtonAssignmentList(out_list); | ||
| 661 | } | ||
| 662 | |||
| 663 | void NPadResource::SetNpadRevision(u64 aruid, NpadRevision revision) { | ||
| 664 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 665 | if (aruid_index >= AruidIndexMax) { | ||
| 666 | return; | ||
| 667 | } | ||
| 668 | |||
| 669 | state[aruid_index].npad_revision = revision; | ||
| 670 | } | ||
| 671 | |||
| 672 | Result NPadResource::SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled) { | ||
| 673 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 674 | if (aruid_index >= AruidIndexMax) { | ||
| 675 | return ResultNpadNotConnected; | ||
| 676 | } | ||
| 677 | |||
| 678 | state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 679 | if (active_data_aruid == aruid) { | ||
| 680 | active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 681 | } | ||
| 682 | return ResultSuccess; | ||
| 683 | } | ||
| 684 | |||
| 685 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_resource.h b/src/core/hle/service/hid/controllers/npad/npad_resource.h deleted file mode 100644 index 4c7e6ab0e..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_resource.h +++ /dev/null | |||
| @@ -1,132 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 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/hid/hid_types.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 14 | #include "core/hle/service/hid/controllers/npad/npad_data.h" | ||
| 15 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 16 | #include "core/hle/service/kernel_helpers.h" | ||
| 17 | |||
| 18 | namespace Core { | ||
| 19 | class System; | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace Kernel { | ||
| 23 | class KReadableEvent; | ||
| 24 | } | ||
| 25 | |||
| 26 | namespace Service::HID { | ||
| 27 | struct DataStatusFlag; | ||
| 28 | |||
| 29 | struct NpadControllerState { | ||
| 30 | bool is_styleset_update_event_initialized{}; | ||
| 31 | INSERT_PADDING_BYTES(0x7); | ||
| 32 | Kernel::KEvent* style_set_update_event{nullptr}; | ||
| 33 | INSERT_PADDING_BYTES(0x27); | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct NpadState { | ||
| 37 | DataStatusFlag flag{}; | ||
| 38 | u64 aruid{}; | ||
| 39 | NPadData data{}; | ||
| 40 | std::array<std::array<Core::HID::NpadButton, StyleIndexCount>, MaxSupportedNpadIdTypes> | ||
| 41 | button_config; | ||
| 42 | std::array<NpadControllerState, MaxSupportedNpadIdTypes> controller_state; | ||
| 43 | NpadRevision npad_revision; | ||
| 44 | }; | ||
| 45 | |||
| 46 | /// Handles Npad request from HID interfaces | ||
| 47 | class NPadResource final { | ||
| 48 | public: | ||
| 49 | explicit NPadResource(KernelHelpers::ServiceContext& context); | ||
| 50 | ~NPadResource(); | ||
| 51 | |||
| 52 | NPadData* GetActiveData(); | ||
| 53 | u64 GetActiveDataAruid(); | ||
| 54 | |||
| 55 | Result RegisterAppletResourceUserId(u64 aruid); | ||
| 56 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 57 | |||
| 58 | void DestroyStyleSetUpdateEvents(u64 aruid); | ||
| 59 | |||
| 60 | Result Activate(u64 aruid); | ||
| 61 | Result Activate(); | ||
| 62 | Result Deactivate(); | ||
| 63 | |||
| 64 | void SetAppletResourceUserId(u64 aruid); | ||
| 65 | std::size_t GetIndexFromAruid(u64 aruid) const; | ||
| 66 | |||
| 67 | Result ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy); | ||
| 68 | Result ClearNpadSystemCommonPolicy(u64 aruid); | ||
| 69 | |||
| 70 | Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set); | ||
| 71 | Result GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, u64 aruid) const; | ||
| 72 | Result GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; | ||
| 73 | Result GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; | ||
| 74 | |||
| 75 | NpadRevision GetNpadRevision(u64 aruid) const; | ||
| 76 | void SetNpadRevision(u64 aruid, NpadRevision revision); | ||
| 77 | |||
| 78 | Result IsSupportedNpadStyleSet(bool& is_set, u64 aruid); | ||
| 79 | |||
| 80 | Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); | ||
| 81 | Result GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const; | ||
| 82 | |||
| 83 | Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode activation_mode); | ||
| 84 | Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, | ||
| 85 | u64 aruid) const; | ||
| 86 | |||
| 87 | Result SetSupportedNpadIdType(u64 aruid, | ||
| 88 | std::span<const Core::HID::NpadIdType> supported_npad_list); | ||
| 89 | bool IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const; | ||
| 90 | |||
| 91 | Result SetLrAssignmentMode(u64 aruid, bool is_enabled); | ||
| 92 | Result GetLrAssignmentMode(bool& is_enabled, u64 aruid) const; | ||
| 93 | |||
| 94 | Result SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); | ||
| 95 | Result IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const; | ||
| 96 | |||
| 97 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | ||
| 98 | Core::HID::NpadIdType npad_id); | ||
| 99 | Result SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 100 | |||
| 101 | Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, | ||
| 102 | Core::HID::NpadIdType npad_id) const; | ||
| 103 | Result SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled); | ||
| 104 | |||
| 105 | Result SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); | ||
| 106 | |||
| 107 | Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, | ||
| 108 | Core::HID::NpadButton button_config); | ||
| 109 | Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 110 | std::size_t index, Core::HID::NpadButton mask, | ||
| 111 | bool is_enabled); | ||
| 112 | void ResetButtonConfig(); | ||
| 113 | |||
| 114 | Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, | ||
| 115 | Core::HID::NpadButton button_assignment); | ||
| 116 | Result ClearNpadCaptureButtonAssignment(u64 aruid); | ||
| 117 | std::size_t GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list, | ||
| 118 | u64 aruid) const; | ||
| 119 | |||
| 120 | Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled); | ||
| 121 | |||
| 122 | private: | ||
| 123 | NPadData active_data{}; | ||
| 124 | AruidRegisterList registration_list{}; | ||
| 125 | std::array<NpadState, AruidIndexMax> state{}; | ||
| 126 | u64 active_data_aruid{}; | ||
| 127 | NpadJoyHoldType default_hold_type{}; | ||
| 128 | s32 ref_counter{}; | ||
| 129 | |||
| 130 | KernelHelpers::ServiceContext& service_context; | ||
| 131 | }; | ||
| 132 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp deleted file mode 100644 index aa0454b5e..000000000 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ /dev/null | |||
| @@ -1,226 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hid/emulated_controller.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | #include "core/hle/kernel/k_event.h" | ||
| 9 | #include "core/hle/kernel/k_readable_event.h" | ||
| 10 | #include "core/hle/service/hid/controllers/palma.h" | ||
| 11 | #include "core/hle/service/kernel_helpers.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) | ||
| 16 | : ControllerBase{hid_core_}, service_context{service_context_} { | ||
| 17 | controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); | ||
| 18 | operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); | ||
| 19 | } | ||
| 20 | |||
| 21 | Palma::~Palma() { | ||
| 22 | service_context.CloseEvent(operation_complete_event); | ||
| 23 | }; | ||
| 24 | |||
| 25 | void Palma::OnInit() {} | ||
| 26 | |||
| 27 | void Palma::OnRelease() {} | ||
| 28 | |||
| 29 | void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 30 | if (!IsControllerActivated()) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, | ||
| 36 | PalmaConnectionHandle& handle) { | ||
| 37 | active_handle.npad_id = npad_id; | ||
| 38 | handle = active_handle; | ||
| 39 | return ResultSuccess; | ||
| 40 | } | ||
| 41 | |||
| 42 | Result Palma::InitializePalma(const PalmaConnectionHandle& handle) { | ||
| 43 | if (handle.npad_id != active_handle.npad_id) { | ||
| 44 | return InvalidPalmaHandle; | ||
| 45 | } | ||
| 46 | Activate(); | ||
| 47 | return ResultSuccess; | ||
| 48 | } | ||
| 49 | |||
| 50 | Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent( | ||
| 51 | const PalmaConnectionHandle& handle) const { | ||
| 52 | if (handle.npad_id != active_handle.npad_id) { | ||
| 53 | LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id); | ||
| 54 | } | ||
| 55 | return operation_complete_event->GetReadableEvent(); | ||
| 56 | } | ||
| 57 | |||
| 58 | Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, | ||
| 59 | PalmaOperationType& operation_type, | ||
| 60 | PalmaOperationData& data) const { | ||
| 61 | if (handle.npad_id != active_handle.npad_id) { | ||
| 62 | return InvalidPalmaHandle; | ||
| 63 | } | ||
| 64 | operation_type = operation.operation; | ||
| 65 | data = operation.data; | ||
| 66 | return ResultSuccess; | ||
| 67 | } | ||
| 68 | |||
| 69 | Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) { | ||
| 70 | if (handle.npad_id != active_handle.npad_id) { | ||
| 71 | return InvalidPalmaHandle; | ||
| 72 | } | ||
| 73 | operation.operation = PalmaOperationType::PlayActivity; | ||
| 74 | operation.result = PalmaResultSuccess; | ||
| 75 | operation.data = {}; | ||
| 76 | operation_complete_event->Signal(); | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 80 | Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) { | ||
| 81 | if (handle.npad_id != active_handle.npad_id) { | ||
| 82 | return InvalidPalmaHandle; | ||
| 83 | } | ||
| 84 | fr_mode = fr_mode_; | ||
| 85 | return ResultSuccess; | ||
| 86 | } | ||
| 87 | |||
| 88 | Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { | ||
| 89 | if (handle.npad_id != active_handle.npad_id) { | ||
| 90 | return InvalidPalmaHandle; | ||
| 91 | } | ||
| 92 | operation.operation = PalmaOperationType::ReadStep; | ||
| 93 | operation.result = PalmaResultSuccess; | ||
| 94 | operation.data = {}; | ||
| 95 | operation_complete_event->Signal(); | ||
| 96 | return ResultSuccess; | ||
| 97 | } | ||
| 98 | |||
| 99 | Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) { | ||
| 100 | if (handle.npad_id != active_handle.npad_id) { | ||
| 101 | return InvalidPalmaHandle; | ||
| 102 | } | ||
| 103 | return ResultSuccess; | ||
| 104 | } | ||
| 105 | |||
| 106 | Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) { | ||
| 107 | if (handle.npad_id != active_handle.npad_id) { | ||
| 108 | return InvalidPalmaHandle; | ||
| 109 | } | ||
| 110 | return ResultSuccess; | ||
| 111 | } | ||
| 112 | |||
| 113 | void Palma::ReadPalmaApplicationSection() {} | ||
| 114 | |||
| 115 | void Palma::WritePalmaApplicationSection() {} | ||
| 116 | |||
| 117 | Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { | ||
| 118 | if (handle.npad_id != active_handle.npad_id) { | ||
| 119 | return InvalidPalmaHandle; | ||
| 120 | } | ||
| 121 | operation.operation = PalmaOperationType::ReadUniqueCode; | ||
| 122 | operation.result = PalmaResultSuccess; | ||
| 123 | operation.data = {}; | ||
| 124 | operation_complete_event->Signal(); | ||
| 125 | return ResultSuccess; | ||
| 126 | } | ||
| 127 | |||
| 128 | Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { | ||
| 129 | if (handle.npad_id != active_handle.npad_id) { | ||
| 130 | return InvalidPalmaHandle; | ||
| 131 | } | ||
| 132 | operation.operation = PalmaOperationType::SetUniqueCodeInvalid; | ||
| 133 | operation.result = PalmaResultSuccess; | ||
| 134 | operation.data = {}; | ||
| 135 | operation_complete_event->Signal(); | ||
| 136 | return ResultSuccess; | ||
| 137 | } | ||
| 138 | |||
| 139 | void Palma::WritePalmaActivityEntry() {} | ||
| 140 | |||
| 141 | Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) { | ||
| 142 | if (handle.npad_id != active_handle.npad_id) { | ||
| 143 | return InvalidPalmaHandle; | ||
| 144 | } | ||
| 145 | operation.operation = PalmaOperationType::WriteRgbLedPatternEntry; | ||
| 146 | operation.result = PalmaResultSuccess; | ||
| 147 | operation.data = {}; | ||
| 148 | operation_complete_event->Signal(); | ||
| 149 | return ResultSuccess; | ||
| 150 | } | ||
| 151 | |||
| 152 | Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, | ||
| 153 | Common::ProcessAddress t_mem, u64 size) { | ||
| 154 | if (handle.npad_id != active_handle.npad_id) { | ||
| 155 | return InvalidPalmaHandle; | ||
| 156 | } | ||
| 157 | operation.operation = PalmaOperationType::WriteWaveEntry; | ||
| 158 | operation.result = PalmaResultSuccess; | ||
| 159 | operation.data = {}; | ||
| 160 | operation_complete_event->Signal(); | ||
| 161 | return ResultSuccess; | ||
| 162 | } | ||
| 163 | |||
| 164 | Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, | ||
| 165 | s32 database_id_version_) { | ||
| 166 | if (handle.npad_id != active_handle.npad_id) { | ||
| 167 | return InvalidPalmaHandle; | ||
| 168 | } | ||
| 169 | database_id_version = database_id_version_; | ||
| 170 | operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; | ||
| 171 | operation.result = PalmaResultSuccess; | ||
| 172 | operation.data[0] = {}; | ||
| 173 | operation_complete_event->Signal(); | ||
| 174 | return ResultSuccess; | ||
| 175 | } | ||
| 176 | |||
| 177 | Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) { | ||
| 178 | if (handle.npad_id != active_handle.npad_id) { | ||
| 179 | return InvalidPalmaHandle; | ||
| 180 | } | ||
| 181 | operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; | ||
| 182 | operation.result = PalmaResultSuccess; | ||
| 183 | operation.data = {}; | ||
| 184 | operation.data[0] = static_cast<u8>(database_id_version); | ||
| 185 | operation_complete_event->Signal(); | ||
| 186 | return ResultSuccess; | ||
| 187 | } | ||
| 188 | |||
| 189 | void Palma::SuspendPalmaFeature() {} | ||
| 190 | |||
| 191 | Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const { | ||
| 192 | if (handle.npad_id != active_handle.npad_id) { | ||
| 193 | return InvalidPalmaHandle; | ||
| 194 | } | ||
| 195 | return operation.result; | ||
| 196 | } | ||
| 197 | void Palma::ReadPalmaPlayLog() {} | ||
| 198 | |||
| 199 | void Palma::ResetPalmaPlayLog() {} | ||
| 200 | |||
| 201 | void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) { | ||
| 202 | // If true controllers are able to be paired | ||
| 203 | is_connectable = is_all_connectable; | ||
| 204 | } | ||
| 205 | |||
| 206 | void Palma::SetIsPalmaPairedConnectable() {} | ||
| 207 | |||
| 208 | Result Palma::PairPalma(const PalmaConnectionHandle& handle) { | ||
| 209 | if (handle.npad_id != active_handle.npad_id) { | ||
| 210 | return InvalidPalmaHandle; | ||
| 211 | } | ||
| 212 | // TODO: Do something | ||
| 213 | return ResultSuccess; | ||
| 214 | } | ||
| 215 | |||
| 216 | void Palma::SetPalmaBoostMode(bool boost_mode) {} | ||
| 217 | |||
| 218 | void Palma::CancelWritePalmaWaveEntry() {} | ||
| 219 | |||
| 220 | void Palma::EnablePalmaBoostMode() {} | ||
| 221 | |||
| 222 | void Palma::GetPalmaBluetoothAddress() {} | ||
| 223 | |||
| 224 | void Palma::SetDisallowedPalmaConnection() {} | ||
| 225 | |||
| 226 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h deleted file mode 100644 index 73884230d..000000000 --- a/src/core/hle/service/hid/controllers/palma.h +++ /dev/null | |||
| @@ -1,162 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include "common/common_funcs.h" | ||
| 8 | #include "common/typed_address.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/errors.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | class KEvent; | ||
| 14 | class KReadableEvent; | ||
| 15 | } // namespace Kernel | ||
| 16 | |||
| 17 | namespace Service::KernelHelpers { | ||
| 18 | class ServiceContext; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Core::HID { | ||
| 22 | class EmulatedController; | ||
| 23 | } // namespace Core::HID | ||
| 24 | |||
| 25 | namespace Service::HID { | ||
| 26 | class Palma final : public ControllerBase { | ||
| 27 | public: | ||
| 28 | using PalmaOperationData = std::array<u8, 0x140>; | ||
| 29 | |||
| 30 | // This is nn::hid::PalmaOperationType | ||
| 31 | enum class PalmaOperationType { | ||
| 32 | PlayActivity, | ||
| 33 | SetFrModeType, | ||
| 34 | ReadStep, | ||
| 35 | EnableStep, | ||
| 36 | ResetStep, | ||
| 37 | ReadApplicationSection, | ||
| 38 | WriteApplicationSection, | ||
| 39 | ReadUniqueCode, | ||
| 40 | SetUniqueCodeInvalid, | ||
| 41 | WriteActivityEntry, | ||
| 42 | WriteRgbLedPatternEntry, | ||
| 43 | WriteWaveEntry, | ||
| 44 | ReadDataBaseIdentificationVersion, | ||
| 45 | WriteDataBaseIdentificationVersion, | ||
| 46 | SuspendFeature, | ||
| 47 | ReadPlayLog, | ||
| 48 | ResetPlayLog, | ||
| 49 | }; | ||
| 50 | |||
| 51 | // This is nn::hid::PalmaWaveSet | ||
| 52 | enum class PalmaWaveSet : u64 { | ||
| 53 | Small, | ||
| 54 | Medium, | ||
| 55 | Large, | ||
| 56 | }; | ||
| 57 | |||
| 58 | // This is nn::hid::PalmaFrModeType | ||
| 59 | enum class PalmaFrModeType : u64 { | ||
| 60 | Off, | ||
| 61 | B01, | ||
| 62 | B02, | ||
| 63 | B03, | ||
| 64 | Downloaded, | ||
| 65 | }; | ||
| 66 | |||
| 67 | // This is nn::hid::PalmaFeature | ||
| 68 | enum class PalmaFeature : u64 { | ||
| 69 | FrMode, | ||
| 70 | RumbleFeedback, | ||
| 71 | Step, | ||
| 72 | MuteSwitch, | ||
| 73 | }; | ||
| 74 | |||
| 75 | // This is nn::hid::PalmaOperationInfo | ||
| 76 | struct PalmaOperationInfo { | ||
| 77 | PalmaOperationType operation{}; | ||
| 78 | Result result{PalmaResultSuccess}; | ||
| 79 | PalmaOperationData data{}; | ||
| 80 | }; | ||
| 81 | static_assert(sizeof(PalmaOperationInfo) == 0x148, "PalmaOperationInfo is an invalid size"); | ||
| 82 | |||
| 83 | // This is nn::hid::PalmaActivityEntry | ||
| 84 | struct PalmaActivityEntry { | ||
| 85 | u32 rgb_led_pattern_index; | ||
| 86 | INSERT_PADDING_BYTES(2); | ||
| 87 | PalmaWaveSet wave_set; | ||
| 88 | u32 wave_index; | ||
| 89 | INSERT_PADDING_BYTES(12); | ||
| 90 | }; | ||
| 91 | static_assert(sizeof(PalmaActivityEntry) == 0x20, "PalmaActivityEntry is an invalid size"); | ||
| 92 | |||
| 93 | struct PalmaConnectionHandle { | ||
| 94 | Core::HID::NpadIdType npad_id; | ||
| 95 | INSERT_PADDING_BYTES(4); // Unknown | ||
| 96 | }; | ||
| 97 | static_assert(sizeof(PalmaConnectionHandle) == 0x8, | ||
| 98 | "PalmaConnectionHandle has incorrect size."); | ||
| 99 | |||
| 100 | explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); | ||
| 101 | ~Palma() override; | ||
| 102 | |||
| 103 | // Called when the controller is initialized | ||
| 104 | void OnInit() override; | ||
| 105 | |||
| 106 | // When the controller is released | ||
| 107 | void OnRelease() override; | ||
| 108 | |||
| 109 | // When the controller is requesting an update for the shared memory | ||
| 110 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 111 | |||
| 112 | Result GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, PalmaConnectionHandle& handle); | ||
| 113 | Result InitializePalma(const PalmaConnectionHandle& handle); | ||
| 114 | Kernel::KReadableEvent& AcquirePalmaOperationCompleteEvent( | ||
| 115 | const PalmaConnectionHandle& handle) const; | ||
| 116 | Result GetPalmaOperationInfo(const PalmaConnectionHandle& handle, | ||
| 117 | PalmaOperationType& operation_type, | ||
| 118 | PalmaOperationData& data) const; | ||
| 119 | Result PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity); | ||
| 120 | Result SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_); | ||
| 121 | Result ReadPalmaStep(const PalmaConnectionHandle& handle); | ||
| 122 | Result EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled); | ||
| 123 | Result ResetPalmaStep(const PalmaConnectionHandle& handle); | ||
| 124 | Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); | ||
| 125 | Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); | ||
| 126 | Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); | ||
| 127 | Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, | ||
| 128 | Common::ProcessAddress t_mem, u64 size); | ||
| 129 | Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, | ||
| 130 | s32 database_id_version_); | ||
| 131 | Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); | ||
| 132 | Result GetPalmaOperationResult(const PalmaConnectionHandle& handle) const; | ||
| 133 | void SetIsPalmaAllConnectable(bool is_all_connectable); | ||
| 134 | Result PairPalma(const PalmaConnectionHandle& handle); | ||
| 135 | void SetPalmaBoostMode(bool boost_mode); | ||
| 136 | |||
| 137 | private: | ||
| 138 | void ReadPalmaApplicationSection(); | ||
| 139 | void WritePalmaApplicationSection(); | ||
| 140 | void WritePalmaActivityEntry(); | ||
| 141 | void SuspendPalmaFeature(); | ||
| 142 | void ReadPalmaPlayLog(); | ||
| 143 | void ResetPalmaPlayLog(); | ||
| 144 | void SetIsPalmaPairedConnectable(); | ||
| 145 | void CancelWritePalmaWaveEntry(); | ||
| 146 | void EnablePalmaBoostMode(); | ||
| 147 | void GetPalmaBluetoothAddress(); | ||
| 148 | void SetDisallowedPalmaConnection(); | ||
| 149 | |||
| 150 | bool is_connectable{}; | ||
| 151 | s32 database_id_version{}; | ||
| 152 | PalmaOperationInfo operation{}; | ||
| 153 | PalmaFrModeType fr_mode{}; | ||
| 154 | PalmaConnectionHandle active_handle{}; | ||
| 155 | |||
| 156 | Core::HID::EmulatedController* controller; | ||
| 157 | |||
| 158 | Kernel::KEvent* operation_complete_event; | ||
| 159 | KernelHelpers::ServiceContext& service_context; | ||
| 160 | }; | ||
| 161 | |||
| 162 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/seven_six_axis.cpp b/src/core/hle/service/hid/controllers/seven_six_axis.cpp deleted file mode 100644 index 495568484..000000000 --- a/src/core/hle/service/hid/controllers/seven_six_axis.cpp +++ /dev/null | |||
| @@ -1,66 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/frontend/emu_window.h" | ||
| 9 | #include "core/hid/emulated_console.h" | ||
| 10 | #include "core/hid/emulated_devices.h" | ||
| 11 | #include "core/hid/hid_core.h" | ||
| 12 | #include "core/hle/service/hid/controllers/seven_six_axis.h" | ||
| 13 | #include "core/memory.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | SevenSixAxis::SevenSixAxis(Core::System& system_) | ||
| 17 | : ControllerBase{system_.HIDCore()}, system{system_} { | ||
| 18 | console = hid_core.GetEmulatedConsole(); | ||
| 19 | } | ||
| 20 | |||
| 21 | SevenSixAxis::~SevenSixAxis() = default; | ||
| 22 | |||
| 23 | void SevenSixAxis::OnInit() {} | ||
| 24 | void SevenSixAxis::OnRelease() {} | ||
| 25 | |||
| 26 | void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 27 | if (!IsControllerActivated() || transfer_memory == 0) { | ||
| 28 | seven_sixaxis_lifo.buffer_count = 0; | ||
| 29 | seven_sixaxis_lifo.buffer_tail = 0; | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; | ||
| 34 | next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; | ||
| 35 | |||
| 36 | const auto motion_status = console->GetMotion(); | ||
| 37 | last_global_timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 38 | |||
| 39 | // This value increments every time the switch goes to sleep | ||
| 40 | next_seven_sixaxis_state.unknown = 1; | ||
| 41 | next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp; | ||
| 42 | next_seven_sixaxis_state.accel = motion_status.accel; | ||
| 43 | next_seven_sixaxis_state.gyro = motion_status.gyro; | ||
| 44 | next_seven_sixaxis_state.quaternion = { | ||
| 45 | { | ||
| 46 | motion_status.quaternion.xyz.y, | ||
| 47 | motion_status.quaternion.xyz.x, | ||
| 48 | -motion_status.quaternion.w, | ||
| 49 | }, | ||
| 50 | -motion_status.quaternion.xyz.z, | ||
| 51 | }; | ||
| 52 | |||
| 53 | seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); | ||
| 54 | system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, | ||
| 55 | sizeof(seven_sixaxis_lifo)); | ||
| 56 | } | ||
| 57 | |||
| 58 | void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { | ||
| 59 | transfer_memory = t_mem; | ||
| 60 | } | ||
| 61 | |||
| 62 | void SevenSixAxis::ResetTimestamp() { | ||
| 63 | last_saved_timestamp = last_global_timestamp; | ||
| 64 | } | ||
| 65 | |||
| 66 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/seven_six_axis.h b/src/core/hle/service/hid/controllers/seven_six_axis.h deleted file mode 100644 index 40e3f5d12..000000000 --- a/src/core/hle/service/hid/controllers/seven_six_axis.h +++ /dev/null | |||
| @@ -1,65 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "common/quaternion.h" | ||
| 8 | #include "common/typed_address.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } // namespace Core | ||
| 15 | |||
| 16 | namespace Core::HID { | ||
| 17 | class EmulatedConsole; | ||
| 18 | } // namespace Core::HID | ||
| 19 | |||
| 20 | namespace Service::HID { | ||
| 21 | class SevenSixAxis final : public ControllerBase { | ||
| 22 | public: | ||
| 23 | explicit SevenSixAxis(Core::System& system_); | ||
| 24 | ~SevenSixAxis() override; | ||
| 25 | |||
| 26 | // Called when the controller is initialized | ||
| 27 | void OnInit() override; | ||
| 28 | |||
| 29 | // When the controller is released | ||
| 30 | void OnRelease() override; | ||
| 31 | |||
| 32 | // When the controller is requesting an update for the shared memory | ||
| 33 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 34 | |||
| 35 | // Called on InitializeSevenSixAxisSensor | ||
| 36 | void SetTransferMemoryAddress(Common::ProcessAddress t_mem); | ||
| 37 | |||
| 38 | // Called on ResetSevenSixAxisSensorTimestamp | ||
| 39 | void ResetTimestamp(); | ||
| 40 | |||
| 41 | private: | ||
| 42 | struct SevenSixAxisState { | ||
| 43 | INSERT_PADDING_WORDS(2); // unused | ||
| 44 | u64 timestamp{}; | ||
| 45 | u64 sampling_number{}; | ||
| 46 | u64 unknown{}; | ||
| 47 | Common::Vec3f accel{}; | ||
| 48 | Common::Vec3f gyro{}; | ||
| 49 | Common::Quaternion<f32> quaternion{}; | ||
| 50 | }; | ||
| 51 | static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); | ||
| 52 | |||
| 53 | Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{}; | ||
| 54 | static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); | ||
| 55 | |||
| 56 | u64 last_saved_timestamp{}; | ||
| 57 | u64 last_global_timestamp{}; | ||
| 58 | |||
| 59 | SevenSixAxisState next_seven_sixaxis_state{}; | ||
| 60 | Common::ProcessAddress transfer_memory{}; | ||
| 61 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 62 | |||
| 63 | Core::System& system; | ||
| 64 | }; | ||
| 65 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp deleted file mode 100644 index 0bc5169c6..000000000 --- a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 6 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 7 | #include "core/hle/service/hid/controllers/shared_memory_holder.h" | ||
| 8 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 9 | #include "core/hle/service/hid/errors.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | SharedMemoryHolder::SharedMemoryHolder() {} | ||
| 13 | |||
| 14 | SharedMemoryHolder::~SharedMemoryHolder() { | ||
| 15 | Finalize(); | ||
| 16 | } | ||
| 17 | |||
| 18 | Result SharedMemoryHolder::Initialize(Core::System& system) { | ||
| 19 | shared_memory = Kernel::KSharedMemory::Create(system.Kernel()); | ||
| 20 | const Result result = shared_memory->Initialize( | ||
| 21 | system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, | ||
| 22 | Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); | ||
| 23 | if (result.IsError()) { | ||
| 24 | return result; | ||
| 25 | } | ||
| 26 | Kernel::KSharedMemory::Register(system.Kernel(), shared_memory); | ||
| 27 | |||
| 28 | is_created = true; | ||
| 29 | is_mapped = true; | ||
| 30 | address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer())); | ||
| 31 | return ResultSuccess; | ||
| 32 | } | ||
| 33 | |||
| 34 | void SharedMemoryHolder::Finalize() { | ||
| 35 | if (address != nullptr) { | ||
| 36 | shared_memory->Close(); | ||
| 37 | } | ||
| 38 | is_created = false; | ||
| 39 | is_mapped = false; | ||
| 40 | address = nullptr; | ||
| 41 | } | ||
| 42 | |||
| 43 | bool SharedMemoryHolder::IsMapped() { | ||
| 44 | return is_mapped; | ||
| 45 | } | ||
| 46 | |||
| 47 | SharedMemoryFormat* SharedMemoryHolder::GetAddress() { | ||
| 48 | return address; | ||
| 49 | } | ||
| 50 | |||
| 51 | Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() { | ||
| 52 | return shared_memory; | ||
| 53 | } | ||
| 54 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.h b/src/core/hle/service/hid/controllers/shared_memory_holder.h deleted file mode 100644 index 943407c00..000000000 --- a/src/core/hle/service/hid/controllers/shared_memory_holder.h +++ /dev/null | |||
| @@ -1,44 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Core { | ||
| 9 | class System; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | class KSharedMemory; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | struct SharedMemoryFormat; | ||
| 18 | |||
| 19 | // This is nn::hid::detail::SharedMemoryHolder | ||
| 20 | class SharedMemoryHolder { | ||
| 21 | public: | ||
| 22 | SharedMemoryHolder(); | ||
| 23 | ~SharedMemoryHolder(); | ||
| 24 | |||
| 25 | Result Initialize(Core::System& system); | ||
| 26 | void Finalize(); | ||
| 27 | |||
| 28 | bool IsMapped(); | ||
| 29 | SharedMemoryFormat* GetAddress(); | ||
| 30 | Kernel::KSharedMemory* GetHandle(); | ||
| 31 | |||
| 32 | private: | ||
| 33 | bool is_owner{}; | ||
| 34 | bool is_created{}; | ||
| 35 | bool is_mapped{}; | ||
| 36 | INSERT_PADDING_BYTES(0x5); | ||
| 37 | Kernel::KSharedMemory* shared_memory; | ||
| 38 | INSERT_PADDING_BYTES(0x38); | ||
| 39 | SharedMemoryFormat* address = nullptr; | ||
| 40 | }; | ||
| 41 | // Correct size is 0x50 bytes | ||
| 42 | static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size"); | ||
| 43 | |||
| 44 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp deleted file mode 100644 index adab60911..000000000 --- a/src/core/hle/service/hid/controllers/six_axis.cpp +++ /dev/null | |||
| @@ -1,421 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/common_types.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 9 | #include "core/hle/service/hid/controllers/six_axis.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | #include "core/hle/service/hid/errors.h" | ||
| 12 | #include "core/hle/service/hid/hid_util.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | |||
| 16 | SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_) | ||
| 17 | : ControllerBase{hid_core_}, npad{npad_} { | ||
| 18 | for (std::size_t i = 0; i < controller_data.size(); ++i) { | ||
| 19 | auto& controller = controller_data[i]; | ||
| 20 | controller.device = hid_core.GetEmulatedControllerByIndex(i); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | SixAxis::~SixAxis() = default; | ||
| 25 | |||
| 26 | void SixAxis::OnInit() {} | ||
| 27 | void SixAxis::OnRelease() {} | ||
| 28 | |||
| 29 | void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 30 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 31 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 32 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 33 | |||
| 34 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 38 | if (!IsControllerActivated()) { | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | for (std::size_t i = 0; i < controller_data.size(); ++i) { | ||
| 43 | NpadSharedMemoryEntry& shared_memory = data->shared_memory_format->npad.npad_entry[i]; | ||
| 44 | auto& controller = controller_data[i]; | ||
| 45 | const auto& controller_type = controller.device->GetNpadStyleIndex(); | ||
| 46 | |||
| 47 | if (controller_type == Core::HID::NpadStyleIndex::None || | ||
| 48 | !controller.device->IsConnected()) { | ||
| 49 | continue; | ||
| 50 | } | ||
| 51 | |||
| 52 | const auto& motion_state = controller.device->GetMotions(); | ||
| 53 | auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; | ||
| 54 | auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; | ||
| 55 | auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state; | ||
| 56 | auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state; | ||
| 57 | auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; | ||
| 58 | auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; | ||
| 59 | |||
| 60 | auto& sixaxis_fullkey_lifo = shared_memory.internal_state.sixaxis_fullkey_lifo; | ||
| 61 | auto& sixaxis_handheld_lifo = shared_memory.internal_state.sixaxis_handheld_lifo; | ||
| 62 | auto& sixaxis_dual_left_lifo = shared_memory.internal_state.sixaxis_dual_left_lifo; | ||
| 63 | auto& sixaxis_dual_right_lifo = shared_memory.internal_state.sixaxis_dual_right_lifo; | ||
| 64 | auto& sixaxis_left_lifo = shared_memory.internal_state.sixaxis_left_lifo; | ||
| 65 | auto& sixaxis_right_lifo = shared_memory.internal_state.sixaxis_right_lifo; | ||
| 66 | |||
| 67 | // Clear previous state | ||
| 68 | sixaxis_fullkey_state = {}; | ||
| 69 | sixaxis_handheld_state = {}; | ||
| 70 | sixaxis_dual_left_state = {}; | ||
| 71 | sixaxis_dual_right_state = {}; | ||
| 72 | sixaxis_left_lifo_state = {}; | ||
| 73 | sixaxis_right_lifo_state = {}; | ||
| 74 | |||
| 75 | if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) { | ||
| 76 | controller.sixaxis_at_rest = true; | ||
| 77 | for (std::size_t e = 0; e < motion_state.size(); ++e) { | ||
| 78 | controller.sixaxis_at_rest = | ||
| 79 | controller.sixaxis_at_rest && motion_state[e].is_at_rest; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state, | ||
| 84 | const Core::HID::ControllerMotion& hid_state) { | ||
| 85 | using namespace std::literals::chrono_literals; | ||
| 86 | static constexpr Core::HID::SixAxisSensorState default_motion_state = { | ||
| 87 | .delta_time = std::chrono::nanoseconds(5ms).count(), | ||
| 88 | .accel = {0, 0, -1.0f}, | ||
| 89 | .orientation = | ||
| 90 | { | ||
| 91 | Common::Vec3f{1.0f, 0, 0}, | ||
| 92 | Common::Vec3f{0, 1.0f, 0}, | ||
| 93 | Common::Vec3f{0, 0, 1.0f}, | ||
| 94 | }, | ||
| 95 | .attribute = {1}, | ||
| 96 | }; | ||
| 97 | if (!controller.sixaxis_sensor_enabled) { | ||
| 98 | state = default_motion_state; | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | if (!Settings::values.motion_enabled.GetValue()) { | ||
| 102 | state = default_motion_state; | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | state.attribute.is_connected.Assign(1); | ||
| 106 | state.delta_time = std::chrono::nanoseconds(5ms).count(); | ||
| 107 | state.accel = hid_state.accel; | ||
| 108 | state.gyro = hid_state.gyro; | ||
| 109 | state.rotation = hid_state.rotation; | ||
| 110 | state.orientation = hid_state.orientation; | ||
| 111 | }; | ||
| 112 | |||
| 113 | switch (controller_type) { | ||
| 114 | case Core::HID::NpadStyleIndex::None: | ||
| 115 | ASSERT(false); | ||
| 116 | break; | ||
| 117 | case Core::HID::NpadStyleIndex::ProController: | ||
| 118 | set_motion_state(sixaxis_fullkey_state, motion_state[0]); | ||
| 119 | break; | ||
| 120 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 121 | set_motion_state(sixaxis_handheld_state, motion_state[0]); | ||
| 122 | break; | ||
| 123 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 124 | set_motion_state(sixaxis_dual_left_state, motion_state[0]); | ||
| 125 | set_motion_state(sixaxis_dual_right_state, motion_state[1]); | ||
| 126 | break; | ||
| 127 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 128 | set_motion_state(sixaxis_left_lifo_state, motion_state[0]); | ||
| 129 | break; | ||
| 130 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 131 | set_motion_state(sixaxis_right_lifo_state, motion_state[1]); | ||
| 132 | break; | ||
| 133 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 134 | using namespace std::literals::chrono_literals; | ||
| 135 | set_motion_state(sixaxis_fullkey_state, motion_state[0]); | ||
| 136 | sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count(); | ||
| 137 | break; | ||
| 138 | default: | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | sixaxis_fullkey_state.sampling_number = | ||
| 143 | sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 144 | sixaxis_handheld_state.sampling_number = | ||
| 145 | sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 146 | sixaxis_dual_left_state.sampling_number = | ||
| 147 | sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 148 | sixaxis_dual_right_state.sampling_number = | ||
| 149 | sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 150 | sixaxis_left_lifo_state.sampling_number = | ||
| 151 | sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 152 | sixaxis_right_lifo_state.sampling_number = | ||
| 153 | sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 154 | |||
| 155 | if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { | ||
| 156 | // This buffer only is updated on handheld on HW | ||
| 157 | sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state); | ||
| 158 | } else { | ||
| 159 | // Handheld doesn't update this buffer on HW | ||
| 160 | sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state); | ||
| 161 | } | ||
| 162 | |||
| 163 | sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state); | ||
| 164 | sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state); | ||
| 165 | sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state); | ||
| 166 | sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 171 | Core::HID::GyroscopeZeroDriftMode drift_mode) { | ||
| 172 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 173 | if (is_valid.IsError()) { | ||
| 174 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 175 | return is_valid; | ||
| 176 | } | ||
| 177 | |||
| 178 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 179 | auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 180 | sixaxis.gyroscope_zero_drift_mode = drift_mode; | ||
| 181 | controller.device->SetGyroscopeZeroDriftMode(drift_mode); | ||
| 182 | |||
| 183 | return ResultSuccess; | ||
| 184 | } | ||
| 185 | |||
| 186 | Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 187 | Core::HID::GyroscopeZeroDriftMode& drift_mode) const { | ||
| 188 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 189 | if (is_valid.IsError()) { | ||
| 190 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 191 | return is_valid; | ||
| 192 | } | ||
| 193 | |||
| 194 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 195 | drift_mode = sixaxis.gyroscope_zero_drift_mode; | ||
| 196 | |||
| 197 | return ResultSuccess; | ||
| 198 | } | ||
| 199 | |||
| 200 | Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 201 | bool& is_at_rest) const { | ||
| 202 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 203 | if (is_valid.IsError()) { | ||
| 204 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 205 | return is_valid; | ||
| 206 | } | ||
| 207 | |||
| 208 | const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 209 | is_at_rest = controller.sixaxis_at_rest; | ||
| 210 | return ResultSuccess; | ||
| 211 | } | ||
| 212 | |||
| 213 | Result SixAxis::LoadSixAxisSensorCalibrationParameter( | ||
| 214 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 215 | Core::HID::SixAxisSensorCalibrationParameter& calibration) const { | ||
| 216 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 217 | if (is_valid.IsError()) { | ||
| 218 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 219 | return is_valid; | ||
| 220 | } | ||
| 221 | |||
| 222 | // TODO: Request this data to the controller. On error return 0xd8ca | ||
| 223 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 224 | calibration = sixaxis.calibration; | ||
| 225 | return ResultSuccess; | ||
| 226 | } | ||
| 227 | |||
| 228 | Result SixAxis::GetSixAxisSensorIcInformation( | ||
| 229 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 230 | Core::HID::SixAxisSensorIcInformation& ic_information) const { | ||
| 231 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 232 | if (is_valid.IsError()) { | ||
| 233 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 234 | return is_valid; | ||
| 235 | } | ||
| 236 | |||
| 237 | // TODO: Request this data to the controller. On error return 0xd8ca | ||
| 238 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 239 | ic_information = sixaxis.ic_information; | ||
| 240 | return ResultSuccess; | ||
| 241 | } | ||
| 242 | |||
| 243 | Result SixAxis::EnableSixAxisSensorUnalteredPassthrough( | ||
| 244 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) { | ||
| 245 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 246 | if (is_valid.IsError()) { | ||
| 247 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 248 | return is_valid; | ||
| 249 | } | ||
| 250 | |||
| 251 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 252 | sixaxis.unaltered_passtrough = is_enabled; | ||
| 253 | return ResultSuccess; | ||
| 254 | } | ||
| 255 | |||
| 256 | Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled( | ||
| 257 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const { | ||
| 258 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 259 | if (is_valid.IsError()) { | ||
| 260 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 261 | return is_valid; | ||
| 262 | } | ||
| 263 | |||
| 264 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 265 | is_enabled = sixaxis.unaltered_passtrough; | ||
| 266 | return ResultSuccess; | ||
| 267 | } | ||
| 268 | |||
| 269 | Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 270 | bool sixaxis_status) { | ||
| 271 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 272 | if (is_valid.IsError()) { | ||
| 273 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 274 | return is_valid; | ||
| 275 | } | ||
| 276 | |||
| 277 | auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 278 | controller.sixaxis_sensor_enabled = sixaxis_status; | ||
| 279 | return ResultSuccess; | ||
| 280 | } | ||
| 281 | |||
| 282 | Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 283 | bool& is_fusion_enabled) const { | ||
| 284 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 285 | if (is_valid.IsError()) { | ||
| 286 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 287 | return is_valid; | ||
| 288 | } | ||
| 289 | |||
| 290 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 291 | is_fusion_enabled = sixaxis.is_fusion_enabled; | ||
| 292 | |||
| 293 | return ResultSuccess; | ||
| 294 | } | ||
| 295 | Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 296 | bool is_fusion_enabled) { | ||
| 297 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 298 | if (is_valid.IsError()) { | ||
| 299 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 300 | return is_valid; | ||
| 301 | } | ||
| 302 | |||
| 303 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 304 | sixaxis.is_fusion_enabled = is_fusion_enabled; | ||
| 305 | |||
| 306 | return ResultSuccess; | ||
| 307 | } | ||
| 308 | |||
| 309 | Result SixAxis::SetSixAxisFusionParameters( | ||
| 310 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 311 | Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { | ||
| 312 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 313 | if (is_valid.IsError()) { | ||
| 314 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 315 | return is_valid; | ||
| 316 | } | ||
| 317 | |||
| 318 | const auto param1 = sixaxis_fusion_parameters.parameter1; | ||
| 319 | if (param1 < 0.0f || param1 > 1.0f) { | ||
| 320 | return InvalidSixAxisFusionRange; | ||
| 321 | } | ||
| 322 | |||
| 323 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 324 | sixaxis.fusion = sixaxis_fusion_parameters; | ||
| 325 | |||
| 326 | return ResultSuccess; | ||
| 327 | } | ||
| 328 | |||
| 329 | Result SixAxis::GetSixAxisFusionParameters( | ||
| 330 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 331 | Core::HID::SixAxisSensorFusionParameters& parameters) const { | ||
| 332 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 333 | if (is_valid.IsError()) { | ||
| 334 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 335 | return is_valid; | ||
| 336 | } | ||
| 337 | |||
| 338 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 339 | parameters = sixaxis.fusion; | ||
| 340 | |||
| 341 | return ResultSuccess; | ||
| 342 | } | ||
| 343 | |||
| 344 | SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( | ||
| 345 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||
| 346 | auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 347 | switch (sixaxis_handle.npad_type) { | ||
| 348 | case Core::HID::NpadStyleIndex::ProController: | ||
| 349 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 350 | return controller.sixaxis_fullkey; | ||
| 351 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 352 | return controller.sixaxis_handheld; | ||
| 353 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 354 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 355 | return controller.sixaxis_dual_left; | ||
| 356 | } | ||
| 357 | return controller.sixaxis_dual_right; | ||
| 358 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 359 | return controller.sixaxis_left; | ||
| 360 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 361 | return controller.sixaxis_right; | ||
| 362 | default: | ||
| 363 | return controller.sixaxis_unknown; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( | ||
| 368 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | ||
| 369 | const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 370 | switch (sixaxis_handle.npad_type) { | ||
| 371 | case Core::HID::NpadStyleIndex::ProController: | ||
| 372 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 373 | return controller.sixaxis_fullkey; | ||
| 374 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 375 | return controller.sixaxis_handheld; | ||
| 376 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 377 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 378 | return controller.sixaxis_dual_left; | ||
| 379 | } | ||
| 380 | return controller.sixaxis_dual_right; | ||
| 381 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 382 | return controller.sixaxis_left; | ||
| 383 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 384 | return controller.sixaxis_right; | ||
| 385 | default: | ||
| 386 | return controller.sixaxis_unknown; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( | ||
| 391 | const Core::HID::SixAxisSensorHandle& device_handle) { | ||
| 392 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 393 | return GetControllerFromNpadIdType(npad_id); | ||
| 394 | } | ||
| 395 | |||
| 396 | const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( | ||
| 397 | const Core::HID::SixAxisSensorHandle& device_handle) const { | ||
| 398 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 399 | return GetControllerFromNpadIdType(npad_id); | ||
| 400 | } | ||
| 401 | |||
| 402 | SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) { | ||
| 403 | if (!IsNpadIdValid(npad_id)) { | ||
| 404 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 405 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 406 | } | ||
| 407 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 408 | return controller_data[npad_index]; | ||
| 409 | } | ||
| 410 | |||
| 411 | const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType( | ||
| 412 | Core::HID::NpadIdType npad_id) const { | ||
| 413 | if (!IsNpadIdValid(npad_id)) { | ||
| 414 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 415 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 416 | } | ||
| 417 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 418 | return controller_data[npad_index]; | ||
| 419 | } | ||
| 420 | |||
| 421 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/six_axis.h b/src/core/hle/service/hid/controllers/six_axis.h deleted file mode 100644 index 4c4f5dc7b..000000000 --- a/src/core/hle/service/hid/controllers/six_axis.h +++ /dev/null | |||
| @@ -1,111 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 9 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 10 | |||
| 11 | namespace Core::HID { | ||
| 12 | class EmulatedController; | ||
| 13 | } // namespace Core::HID | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | class NPad; | ||
| 17 | |||
| 18 | class SixAxis final : public ControllerBase { | ||
| 19 | public: | ||
| 20 | explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_); | ||
| 21 | ~SixAxis() override; | ||
| 22 | |||
| 23 | // Called when the controller is initialized | ||
| 24 | void OnInit() override; | ||
| 25 | |||
| 26 | // When the controller is released | ||
| 27 | void OnRelease() override; | ||
| 28 | |||
| 29 | // When the controller is requesting an update for the shared memory | ||
| 30 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 31 | |||
| 32 | Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 33 | Core::HID::GyroscopeZeroDriftMode drift_mode); | ||
| 34 | Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 35 | Core::HID::GyroscopeZeroDriftMode& drift_mode) const; | ||
| 36 | Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 37 | bool& is_at_rest) const; | ||
| 38 | Result EnableSixAxisSensorUnalteredPassthrough( | ||
| 39 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled); | ||
| 40 | Result IsSixAxisSensorUnalteredPassthroughEnabled( | ||
| 41 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const; | ||
| 42 | Result LoadSixAxisSensorCalibrationParameter( | ||
| 43 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 44 | Core::HID::SixAxisSensorCalibrationParameter& calibration) const; | ||
| 45 | Result GetSixAxisSensorIcInformation( | ||
| 46 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 47 | Core::HID::SixAxisSensorIcInformation& ic_information) const; | ||
| 48 | Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 49 | bool sixaxis_status); | ||
| 50 | Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 51 | bool& is_fusion_enabled) const; | ||
| 52 | Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 53 | bool is_fusion_enabled); | ||
| 54 | Result SetSixAxisFusionParameters( | ||
| 55 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 56 | Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); | ||
| 57 | Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 58 | Core::HID::SixAxisSensorFusionParameters& parameters) const; | ||
| 59 | |||
| 60 | private: | ||
| 61 | static constexpr std::size_t NPAD_COUNT = 10; | ||
| 62 | |||
| 63 | struct SixaxisParameters { | ||
| 64 | bool is_fusion_enabled{true}; | ||
| 65 | bool unaltered_passtrough{false}; | ||
| 66 | Core::HID::SixAxisSensorFusionParameters fusion{}; | ||
| 67 | Core::HID::SixAxisSensorCalibrationParameter calibration{}; | ||
| 68 | Core::HID::SixAxisSensorIcInformation ic_information{}; | ||
| 69 | Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{ | ||
| 70 | Core::HID::GyroscopeZeroDriftMode::Standard}; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct NpadControllerData { | ||
| 74 | Core::HID::EmulatedController* device = nullptr; | ||
| 75 | |||
| 76 | // Motion parameters | ||
| 77 | bool sixaxis_at_rest{true}; | ||
| 78 | bool sixaxis_sensor_enabled{true}; | ||
| 79 | SixaxisParameters sixaxis_fullkey{}; | ||
| 80 | SixaxisParameters sixaxis_handheld{}; | ||
| 81 | SixaxisParameters sixaxis_dual_left{}; | ||
| 82 | SixaxisParameters sixaxis_dual_right{}; | ||
| 83 | SixaxisParameters sixaxis_left{}; | ||
| 84 | SixaxisParameters sixaxis_right{}; | ||
| 85 | SixaxisParameters sixaxis_unknown{}; | ||
| 86 | |||
| 87 | // Current pad state | ||
| 88 | Core::HID::SixAxisSensorState sixaxis_fullkey_state{}; | ||
| 89 | Core::HID::SixAxisSensorState sixaxis_handheld_state{}; | ||
| 90 | Core::HID::SixAxisSensorState sixaxis_dual_left_state{}; | ||
| 91 | Core::HID::SixAxisSensorState sixaxis_dual_right_state{}; | ||
| 92 | Core::HID::SixAxisSensorState sixaxis_left_lifo_state{}; | ||
| 93 | Core::HID::SixAxisSensorState sixaxis_right_lifo_state{}; | ||
| 94 | int callback_key{}; | ||
| 95 | }; | ||
| 96 | |||
| 97 | SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 98 | const SixaxisParameters& GetSixaxisState( | ||
| 99 | const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 100 | |||
| 101 | NpadControllerData& GetControllerFromHandle( | ||
| 102 | const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 103 | const NpadControllerData& GetControllerFromHandle( | ||
| 104 | const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 105 | NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); | ||
| 106 | const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; | ||
| 107 | |||
| 108 | std::shared_ptr<NPad> npad; | ||
| 109 | std::array<NpadControllerData, NPAD_COUNT> controller_data{}; | ||
| 110 | }; | ||
| 111 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/sleep_button.cpp b/src/core/hle/service/hid/controllers/sleep_button.cpp deleted file mode 100644 index d44b1f4cc..000000000 --- a/src/core/hle/service/hid/controllers/sleep_button.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/sleep_button.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | SleepButton::SleepButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | SleepButton::~SleepButton() = default; | ||
| 14 | |||
| 15 | void SleepButton::OnInit() {} | ||
| 16 | |||
| 17 | void SleepButton::OnRelease() {} | ||
| 18 | |||
| 19 | void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->capture_button.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/sleep_button.h b/src/core/hle/service/hid/controllers/sleep_button.h deleted file mode 100644 index 59964bf63..000000000 --- a/src/core/hle/service/hid/controllers/sleep_button.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class SleepButton final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit SleepButton(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~SleepButton() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp deleted file mode 100644 index b585a5829..000000000 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ /dev/null | |||
| @@ -1,132 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "common/settings.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/frontend/emu_window.h" | ||
| 9 | #include "core/hid/emulated_console.h" | ||
| 10 | #include "core/hid/hid_core.h" | ||
| 11 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 12 | #include "core/hle/service/hid/controllers/touchscreen.h" | ||
| 13 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | |||
| 17 | TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_) | ||
| 18 | : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), | ||
| 19 | touchscreen_height(Layout::ScreenUndocked::Height) { | ||
| 20 | console = hid_core.GetEmulatedConsole(); | ||
| 21 | } | ||
| 22 | |||
| 23 | TouchScreen::~TouchScreen() = default; | ||
| 24 | |||
| 25 | void TouchScreen::OnInit() {} | ||
| 26 | |||
| 27 | void TouchScreen::OnRelease() {} | ||
| 28 | |||
| 29 | void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 30 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 31 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 32 | |||
| 33 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | TouchScreenSharedMemoryFormat& shared_memory = data->shared_memory_format->touch_screen; | ||
| 38 | shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 39 | |||
| 40 | if (!IsControllerActivated()) { | ||
| 41 | shared_memory.touch_screen_lifo.buffer_count = 0; | ||
| 42 | shared_memory.touch_screen_lifo.buffer_tail = 0; | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | const auto touch_status = console->GetTouch(); | ||
| 47 | for (std::size_t id = 0; id < MAX_FINGERS; id++) { | ||
| 48 | const auto& current_touch = touch_status[id]; | ||
| 49 | auto& finger = fingers[id]; | ||
| 50 | finger.id = current_touch.id; | ||
| 51 | |||
| 52 | if (finger.attribute.start_touch) { | ||
| 53 | finger.attribute.raw = 0; | ||
| 54 | continue; | ||
| 55 | } | ||
| 56 | |||
| 57 | if (finger.attribute.end_touch) { | ||
| 58 | finger.attribute.raw = 0; | ||
| 59 | finger.pressed = false; | ||
| 60 | continue; | ||
| 61 | } | ||
| 62 | |||
| 63 | if (!finger.pressed && current_touch.pressed) { | ||
| 64 | // Ignore all touch fingers if disabled | ||
| 65 | if (!Settings::values.touchscreen.enabled) { | ||
| 66 | continue; | ||
| 67 | } | ||
| 68 | |||
| 69 | finger.attribute.start_touch.Assign(1); | ||
| 70 | finger.pressed = true; | ||
| 71 | finger.position = current_touch.position; | ||
| 72 | continue; | ||
| 73 | } | ||
| 74 | |||
| 75 | if (finger.pressed && !current_touch.pressed) { | ||
| 76 | finger.attribute.raw = 0; | ||
| 77 | finger.attribute.end_touch.Assign(1); | ||
| 78 | continue; | ||
| 79 | } | ||
| 80 | |||
| 81 | // Only update position if touch is not on a special frame | ||
| 82 | finger.position = current_touch.position; | ||
| 83 | } | ||
| 84 | |||
| 85 | std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers; | ||
| 86 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 87 | [](const auto& finger) { return finger.pressed; }); | ||
| 88 | const auto active_fingers_count = | ||
| 89 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 90 | |||
| 91 | const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count()); | ||
| 92 | const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state; | ||
| 93 | |||
| 94 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 95 | next_state.entry_count = static_cast<s32>(active_fingers_count); | ||
| 96 | |||
| 97 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { | ||
| 98 | auto& touch_entry = next_state.states[id]; | ||
| 99 | if (id < active_fingers_count) { | ||
| 100 | const auto& [active_x, active_y] = active_fingers[id].position; | ||
| 101 | touch_entry.position = { | ||
| 102 | .x = static_cast<u16>(active_x * static_cast<float>(touchscreen_width)), | ||
| 103 | .y = static_cast<u16>(active_y * static_cast<float>(touchscreen_height)), | ||
| 104 | }; | ||
| 105 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | ||
| 106 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | ||
| 107 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | ||
| 108 | touch_entry.delta_time = timestamp - active_fingers[id].last_touch; | ||
| 109 | fingers[active_fingers[id].id].last_touch = timestamp; | ||
| 110 | touch_entry.finger = active_fingers[id].id; | ||
| 111 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; | ||
| 112 | } else { | ||
| 113 | // Clear touch entry | ||
| 114 | touch_entry.attribute.raw = 0; | ||
| 115 | touch_entry.position = {}; | ||
| 116 | touch_entry.diameter_x = 0; | ||
| 117 | touch_entry.diameter_y = 0; | ||
| 118 | touch_entry.rotation_angle = 0; | ||
| 119 | touch_entry.delta_time = 0; | ||
| 120 | touch_entry.finger = 0; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | shared_memory.touch_screen_lifo.WriteNextEntry(next_state); | ||
| 125 | } | ||
| 126 | |||
| 127 | void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { | ||
| 128 | touchscreen_width = width; | ||
| 129 | touchscreen_height = height; | ||
| 130 | } | ||
| 131 | |||
| 132 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h deleted file mode 100644 index 945d359be..000000000 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ /dev/null | |||
| @@ -1,43 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/touch_types.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedConsole; | ||
| 14 | } // namespace Core::HID | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | struct TouchScreenSharedMemoryFormat; | ||
| 18 | |||
| 19 | class TouchScreen final : public ControllerBase { | ||
| 20 | public: | ||
| 21 | explicit TouchScreen(Core::HID::HIDCore& hid_core_); | ||
| 22 | ~TouchScreen() override; | ||
| 23 | |||
| 24 | // Called when the controller is initialized | ||
| 25 | void OnInit() override; | ||
| 26 | |||
| 27 | // When the controller is released | ||
| 28 | void OnRelease() override; | ||
| 29 | |||
| 30 | // When the controller is requesting an update for the shared memory | ||
| 31 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 32 | |||
| 33 | void SetTouchscreenDimensions(u32 width, u32 height); | ||
| 34 | |||
| 35 | private: | ||
| 36 | TouchScreenState next_state{}; | ||
| 37 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 38 | |||
| 39 | std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; | ||
| 40 | u32 touchscreen_width; | ||
| 41 | u32 touchscreen_height; | ||
| 42 | }; | ||
| 43 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/debug_pad_types.h b/src/core/hle/service/hid/controllers/types/debug_pad_types.h deleted file mode 100644 index a96171b62..000000000 --- a/src/core/hle/service/hid/controllers/types/debug_pad_types.h +++ /dev/null | |||
| @@ -1,31 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | // This is nn::hid::DebugPadAttribute | ||
| 13 | struct DebugPadAttribute { | ||
| 14 | union { | ||
| 15 | u32 raw{}; | ||
| 16 | BitField<0, 1, u32> connected; | ||
| 17 | }; | ||
| 18 | }; | ||
| 19 | static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size"); | ||
| 20 | |||
| 21 | // This is nn::hid::DebugPadState | ||
| 22 | struct DebugPadState { | ||
| 23 | s64 sampling_number{}; | ||
| 24 | DebugPadAttribute attribute{}; | ||
| 25 | Core::HID::DebugPadButton pad_state{}; | ||
| 26 | Core::HID::AnalogStickState r_stick{}; | ||
| 27 | Core::HID::AnalogStickState l_stick{}; | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); | ||
| 30 | |||
| 31 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/gesture_types.h b/src/core/hle/service/hid/controllers/types/gesture_types.h deleted file mode 100644 index b4f034cd3..000000000 --- a/src/core/hle/service/hid/controllers/types/gesture_types.h +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include "common/bit_field.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "common/point.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | static constexpr size_t MAX_FINGERS = 16; | ||
| 13 | static constexpr size_t MAX_POINTS = 4; | ||
| 14 | |||
| 15 | // This is nn::hid::GestureType | ||
| 16 | enum class GestureType : u32 { | ||
| 17 | Idle, // Nothing touching the screen | ||
| 18 | Complete, // Set at the end of a touch event | ||
| 19 | Cancel, // Set when the number of fingers change | ||
| 20 | Touch, // A finger just touched the screen | ||
| 21 | Press, // Set if last type is touch and the finger hasn't moved | ||
| 22 | Tap, // Fast press then release | ||
| 23 | Pan, // All points moving together across the screen | ||
| 24 | Swipe, // Fast press movement and release of a single point | ||
| 25 | Pinch, // All points moving away/closer to the midpoint | ||
| 26 | Rotate, // All points rotating from the midpoint | ||
| 27 | }; | ||
| 28 | |||
| 29 | // This is nn::hid::GestureDirection | ||
| 30 | enum class GestureDirection : u32 { | ||
| 31 | None, | ||
| 32 | Left, | ||
| 33 | Up, | ||
| 34 | Right, | ||
| 35 | Down, | ||
| 36 | }; | ||
| 37 | |||
| 38 | // This is nn::hid::GestureAttribute | ||
| 39 | struct GestureAttribute { | ||
| 40 | union { | ||
| 41 | u32 raw{}; | ||
| 42 | |||
| 43 | BitField<4, 1, u32> is_new_touch; | ||
| 44 | BitField<8, 1, u32> is_double_tap; | ||
| 45 | }; | ||
| 46 | }; | ||
| 47 | static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); | ||
| 48 | |||
| 49 | // This is nn::hid::GestureState | ||
| 50 | struct GestureState { | ||
| 51 | s64 sampling_number{}; | ||
| 52 | s64 detection_count{}; | ||
| 53 | GestureType type{GestureType::Idle}; | ||
| 54 | GestureDirection direction{GestureDirection::None}; | ||
| 55 | Common::Point<s32> pos{}; | ||
| 56 | Common::Point<s32> delta{}; | ||
| 57 | f32 vel_x{}; | ||
| 58 | f32 vel_y{}; | ||
| 59 | GestureAttribute attributes{}; | ||
| 60 | f32 scale{}; | ||
| 61 | f32 rotation_angle{}; | ||
| 62 | s32 point_count{}; | ||
| 63 | std::array<Common::Point<s32>, 4> points{}; | ||
| 64 | }; | ||
| 65 | static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); | ||
| 66 | |||
| 67 | struct GestureProperties { | ||
| 68 | std::array<Common::Point<s32>, MAX_POINTS> points{}; | ||
| 69 | std::size_t active_points{}; | ||
| 70 | Common::Point<s32> mid_point{}; | ||
| 71 | s64 detection_count{}; | ||
| 72 | u64 delta_time{}; | ||
| 73 | f32 average_distance{}; | ||
| 74 | f32 angle{}; | ||
| 75 | }; | ||
| 76 | |||
| 77 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/keyboard_types.h b/src/core/hle/service/hid/controllers/types/keyboard_types.h deleted file mode 100644 index f44a536b9..000000000 --- a/src/core/hle/service/hid/controllers/types/keyboard_types.h +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | // This is nn::hid::detail::KeyboardState | ||
| 12 | struct KeyboardState { | ||
| 13 | s64 sampling_number{}; | ||
| 14 | Core::HID::KeyboardModifier modifier{}; | ||
| 15 | Core::HID::KeyboardAttribute attribute{}; | ||
| 16 | Core::HID::KeyboardKey key{}; | ||
| 17 | }; | ||
| 18 | static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); | ||
| 19 | |||
| 20 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/mouse_types.h b/src/core/hle/service/hid/controllers/types/mouse_types.h deleted file mode 100644 index 8bd6e167c..000000000 --- a/src/core/hle/service/hid/controllers/types/mouse_types.h +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID {} // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/npad_types.h b/src/core/hle/service/hid/controllers/types/npad_types.h deleted file mode 100644 index 419c33a8c..000000000 --- a/src/core/hle/service/hid/controllers/types/npad_types.h +++ /dev/null | |||
| @@ -1,255 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_funcs.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hid/hid_types.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | static constexpr std::size_t MaxSupportedNpadIdTypes = 10; | ||
| 13 | static constexpr std::size_t StyleIndexCount = 7; | ||
| 14 | |||
| 15 | // This is nn::hid::NpadJoyHoldType | ||
| 16 | enum class NpadJoyHoldType : u64 { | ||
| 17 | Vertical = 0, | ||
| 18 | Horizontal = 1, | ||
| 19 | }; | ||
| 20 | |||
| 21 | // This is nn::hid::NpadJoyAssignmentMode | ||
| 22 | enum class NpadJoyAssignmentMode : u32 { | ||
| 23 | Dual = 0, | ||
| 24 | Single = 1, | ||
| 25 | }; | ||
| 26 | |||
| 27 | // This is nn::hid::NpadJoyDeviceType | ||
| 28 | enum class NpadJoyDeviceType : s64 { | ||
| 29 | Left = 0, | ||
| 30 | Right = 1, | ||
| 31 | }; | ||
| 32 | |||
| 33 | // This is nn::hid::NpadHandheldActivationMode | ||
| 34 | enum class NpadHandheldActivationMode : u64 { | ||
| 35 | Dual = 0, | ||
| 36 | Single = 1, | ||
| 37 | None = 2, | ||
| 38 | MaxActivationMode = 3, | ||
| 39 | }; | ||
| 40 | |||
| 41 | // This is nn::hid::system::AppletFooterUiAttributesSet | ||
| 42 | struct AppletFooterUiAttributes { | ||
| 43 | INSERT_PADDING_BYTES(0x4); | ||
| 44 | }; | ||
| 45 | |||
| 46 | // This is nn::hid::system::AppletFooterUiType | ||
| 47 | enum class AppletFooterUiType : u8 { | ||
| 48 | None = 0, | ||
| 49 | HandheldNone = 1, | ||
| 50 | HandheldJoyConLeftOnly = 2, | ||
| 51 | HandheldJoyConRightOnly = 3, | ||
| 52 | HandheldJoyConLeftJoyConRight = 4, | ||
| 53 | JoyDual = 5, | ||
| 54 | JoyDualLeftOnly = 6, | ||
| 55 | JoyDualRightOnly = 7, | ||
| 56 | JoyLeftHorizontal = 8, | ||
| 57 | JoyLeftVertical = 9, | ||
| 58 | JoyRightHorizontal = 10, | ||
| 59 | JoyRightVertical = 11, | ||
| 60 | SwitchProController = 12, | ||
| 61 | CompatibleProController = 13, | ||
| 62 | CompatibleJoyCon = 14, | ||
| 63 | LarkHvc1 = 15, | ||
| 64 | LarkHvc2 = 16, | ||
| 65 | LarkNesLeft = 17, | ||
| 66 | LarkNesRight = 18, | ||
| 67 | Lucia = 19, | ||
| 68 | Verification = 20, | ||
| 69 | Lagon = 21, | ||
| 70 | }; | ||
| 71 | |||
| 72 | using AppletFooterUiVariant = u8; | ||
| 73 | |||
| 74 | // This is "nn::hid::system::AppletDetailedUiType". | ||
| 75 | struct AppletDetailedUiType { | ||
| 76 | AppletFooterUiVariant ui_variant; | ||
| 77 | INSERT_PADDING_BYTES(0x2); | ||
| 78 | AppletFooterUiType footer; | ||
| 79 | }; | ||
| 80 | static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); | ||
| 81 | // This is nn::hid::NpadCommunicationMode | ||
| 82 | enum class NpadCommunicationMode : u64 { | ||
| 83 | Mode_5ms = 0, | ||
| 84 | Mode_10ms = 1, | ||
| 85 | Mode_15ms = 2, | ||
| 86 | Default = 3, | ||
| 87 | }; | ||
| 88 | |||
| 89 | enum class NpadRevision : u32 { | ||
| 90 | Revision0 = 0, | ||
| 91 | Revision1 = 1, | ||
| 92 | Revision2 = 2, | ||
| 93 | Revision3 = 3, | ||
| 94 | }; | ||
| 95 | |||
| 96 | // This is nn::hid::detail::ColorAttribute | ||
| 97 | enum class ColorAttribute : u32 { | ||
| 98 | Ok = 0, | ||
| 99 | ReadError = 1, | ||
| 100 | NoController = 2, | ||
| 101 | }; | ||
| 102 | static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); | ||
| 103 | |||
| 104 | // This is nn::hid::detail::NpadFullKeyColorState | ||
| 105 | struct NpadFullKeyColorState { | ||
| 106 | ColorAttribute attribute{ColorAttribute::NoController}; | ||
| 107 | Core::HID::NpadControllerColor fullkey{}; | ||
| 108 | }; | ||
| 109 | static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); | ||
| 110 | |||
| 111 | // This is nn::hid::detail::NpadJoyColorState | ||
| 112 | struct NpadJoyColorState { | ||
| 113 | ColorAttribute attribute{ColorAttribute::NoController}; | ||
| 114 | Core::HID::NpadControllerColor left{}; | ||
| 115 | Core::HID::NpadControllerColor right{}; | ||
| 116 | }; | ||
| 117 | static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); | ||
| 118 | |||
| 119 | // This is nn::hid::NpadAttribute | ||
| 120 | struct NpadAttribute { | ||
| 121 | union { | ||
| 122 | u32 raw{}; | ||
| 123 | BitField<0, 1, u32> is_connected; | ||
| 124 | BitField<1, 1, u32> is_wired; | ||
| 125 | BitField<2, 1, u32> is_left_connected; | ||
| 126 | BitField<3, 1, u32> is_left_wired; | ||
| 127 | BitField<4, 1, u32> is_right_connected; | ||
| 128 | BitField<5, 1, u32> is_right_wired; | ||
| 129 | }; | ||
| 130 | }; | ||
| 131 | static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); | ||
| 132 | |||
| 133 | // This is nn::hid::NpadFullKeyState | ||
| 134 | // This is nn::hid::NpadHandheldState | ||
| 135 | // This is nn::hid::NpadJoyDualState | ||
| 136 | // This is nn::hid::NpadJoyLeftState | ||
| 137 | // This is nn::hid::NpadJoyRightState | ||
| 138 | // This is nn::hid::NpadPalmaState | ||
| 139 | // This is nn::hid::NpadSystemExtState | ||
| 140 | struct NPadGenericState { | ||
| 141 | s64_le sampling_number{}; | ||
| 142 | Core::HID::NpadButtonState npad_buttons{}; | ||
| 143 | Core::HID::AnalogStickState l_stick{}; | ||
| 144 | Core::HID::AnalogStickState r_stick{}; | ||
| 145 | NpadAttribute connection_status{}; | ||
| 146 | INSERT_PADDING_BYTES(4); // Reserved | ||
| 147 | }; | ||
| 148 | static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); | ||
| 149 | |||
| 150 | // This is nn::hid::server::NpadGcTriggerState | ||
| 151 | struct NpadGcTriggerState { | ||
| 152 | s64 sampling_number{}; | ||
| 153 | s32 l_analog{}; | ||
| 154 | s32 r_analog{}; | ||
| 155 | }; | ||
| 156 | static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); | ||
| 157 | |||
| 158 | // This is nn::hid::NpadSystemProperties | ||
| 159 | struct NPadSystemProperties { | ||
| 160 | union { | ||
| 161 | s64 raw{}; | ||
| 162 | BitField<0, 1, s64> is_charging_joy_dual; | ||
| 163 | BitField<1, 1, s64> is_charging_joy_left; | ||
| 164 | BitField<2, 1, s64> is_charging_joy_right; | ||
| 165 | BitField<3, 1, s64> is_powered_joy_dual; | ||
| 166 | BitField<4, 1, s64> is_powered_joy_left; | ||
| 167 | BitField<5, 1, s64> is_powered_joy_right; | ||
| 168 | BitField<9, 1, s64> is_system_unsupported_button; | ||
| 169 | BitField<10, 1, s64> is_system_ext_unsupported_button; | ||
| 170 | BitField<11, 1, s64> is_vertical; | ||
| 171 | BitField<12, 1, s64> is_horizontal; | ||
| 172 | BitField<13, 1, s64> use_plus; | ||
| 173 | BitField<14, 1, s64> use_minus; | ||
| 174 | BitField<15, 1, s64> use_directional_buttons; | ||
| 175 | }; | ||
| 176 | }; | ||
| 177 | static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); | ||
| 178 | |||
| 179 | // This is nn::hid::NpadSystemButtonProperties | ||
| 180 | struct NpadSystemButtonProperties { | ||
| 181 | union { | ||
| 182 | s32 raw{}; | ||
| 183 | BitField<0, 1, s32> is_home_button_protection_enabled; | ||
| 184 | }; | ||
| 185 | }; | ||
| 186 | static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); | ||
| 187 | |||
| 188 | // This is nn::hid::system::DeviceType | ||
| 189 | struct DeviceType { | ||
| 190 | union { | ||
| 191 | u32 raw{}; | ||
| 192 | BitField<0, 1, s32> fullkey; | ||
| 193 | BitField<1, 1, s32> debug_pad; | ||
| 194 | BitField<2, 1, s32> handheld_left; | ||
| 195 | BitField<3, 1, s32> handheld_right; | ||
| 196 | BitField<4, 1, s32> joycon_left; | ||
| 197 | BitField<5, 1, s32> joycon_right; | ||
| 198 | BitField<6, 1, s32> palma; | ||
| 199 | BitField<7, 1, s32> lark_hvc_left; | ||
| 200 | BitField<8, 1, s32> lark_hvc_right; | ||
| 201 | BitField<9, 1, s32> lark_nes_left; | ||
| 202 | BitField<10, 1, s32> lark_nes_right; | ||
| 203 | BitField<11, 1, s32> handheld_lark_hvc_left; | ||
| 204 | BitField<12, 1, s32> handheld_lark_hvc_right; | ||
| 205 | BitField<13, 1, s32> handheld_lark_nes_left; | ||
| 206 | BitField<14, 1, s32> handheld_lark_nes_right; | ||
| 207 | BitField<15, 1, s32> lucia; | ||
| 208 | BitField<16, 1, s32> lagon; | ||
| 209 | BitField<17, 1, s32> lager; | ||
| 210 | BitField<31, 1, s32> system; | ||
| 211 | }; | ||
| 212 | }; | ||
| 213 | |||
| 214 | // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl | ||
| 215 | struct NfcXcdDeviceHandleStateImpl { | ||
| 216 | u64 handle{}; | ||
| 217 | bool is_available{}; | ||
| 218 | bool is_activated{}; | ||
| 219 | INSERT_PADDING_BYTES(0x6); // Reserved | ||
| 220 | u64 sampling_number{}; | ||
| 221 | }; | ||
| 222 | static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, | ||
| 223 | "NfcXcdDeviceHandleStateImpl is an invalid size"); | ||
| 224 | |||
| 225 | // This is nn::hid::NpadLarkType | ||
| 226 | enum class NpadLarkType : u32 { | ||
| 227 | Invalid, | ||
| 228 | H1, | ||
| 229 | H2, | ||
| 230 | NL, | ||
| 231 | NR, | ||
| 232 | }; | ||
| 233 | |||
| 234 | // This is nn::hid::NpadLuciaType | ||
| 235 | enum class NpadLuciaType : u32 { | ||
| 236 | Invalid, | ||
| 237 | J, | ||
| 238 | E, | ||
| 239 | U, | ||
| 240 | }; | ||
| 241 | |||
| 242 | // This is nn::hid::NpadLagonType | ||
| 243 | enum class NpadLagonType : u32 { | ||
| 244 | Invalid, | ||
| 245 | }; | ||
| 246 | |||
| 247 | // This is nn::hid::NpadLagerType | ||
| 248 | enum class NpadLagerType : u32 { | ||
| 249 | Invalid, | ||
| 250 | J, | ||
| 251 | E, | ||
| 252 | U, | ||
| 253 | }; | ||
| 254 | |||
| 255 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/shared_memory_format.h b/src/core/hle/service/hid/controllers/types/shared_memory_format.h deleted file mode 100644 index 976043b9c..000000000 --- a/src/core/hle/service/hid/controllers/types/shared_memory_format.h +++ /dev/null | |||
| @@ -1,240 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/vector_math.h" | ||
| 9 | #include "core/hid/hid_types.h" | ||
| 10 | #include "core/hle/service/hid//controllers/types/debug_pad_types.h" | ||
| 11 | #include "core/hle/service/hid//controllers/types/keyboard_types.h" | ||
| 12 | #include "core/hle/service/hid//controllers/types/mouse_types.h" | ||
| 13 | #include "core/hle/service/hid//controllers/types/npad_types.h" | ||
| 14 | #include "core/hle/service/hid//controllers/types/touch_types.h" | ||
| 15 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 16 | |||
| 17 | namespace Service::HID { | ||
| 18 | static const std::size_t HidEntryCount = 17; | ||
| 19 | |||
| 20 | struct CommonHeader { | ||
| 21 | s64 timestamp{}; | ||
| 22 | s64 total_entry_count{}; | ||
| 23 | s64 last_entry_index{}; | ||
| 24 | s64 entry_count{}; | ||
| 25 | }; | ||
| 26 | static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); | ||
| 27 | |||
| 28 | // This is nn::hid::detail::DebugPadSharedMemoryFormat | ||
| 29 | struct DebugPadSharedMemoryFormat { | ||
| 30 | // This is nn::hid::detail::DebugPadLifo | ||
| 31 | Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{}; | ||
| 32 | static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); | ||
| 33 | INSERT_PADDING_WORDS(0x4E); | ||
| 34 | }; | ||
| 35 | static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400, | ||
| 36 | "DebugPadSharedMemoryFormat is an invalid size"); | ||
| 37 | |||
| 38 | // This is nn::hid::detail::TouchScreenSharedMemoryFormat | ||
| 39 | struct TouchScreenSharedMemoryFormat { | ||
| 40 | // This is nn::hid::detail::TouchScreenLifo | ||
| 41 | Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{}; | ||
| 42 | static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); | ||
| 43 | INSERT_PADDING_WORDS(0xF2); | ||
| 44 | }; | ||
| 45 | static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000, | ||
| 46 | "TouchScreenSharedMemoryFormat is an invalid size"); | ||
| 47 | |||
| 48 | // This is nn::hid::detail::MouseSharedMemoryFormat | ||
| 49 | struct MouseSharedMemoryFormat { | ||
| 50 | // This is nn::hid::detail::MouseLifo | ||
| 51 | Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{}; | ||
| 52 | static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); | ||
| 53 | INSERT_PADDING_WORDS(0x2C); | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(MouseSharedMemoryFormat) == 0x400, | ||
| 56 | "MouseSharedMemoryFormat is an invalid size"); | ||
| 57 | |||
| 58 | // This is nn::hid::detail::KeyboardSharedMemoryFormat | ||
| 59 | struct KeyboardSharedMemoryFormat { | ||
| 60 | // This is nn::hid::detail::KeyboardLifo | ||
| 61 | Lifo<KeyboardState, HidEntryCount> keyboard_lifo{}; | ||
| 62 | static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); | ||
| 63 | INSERT_PADDING_WORDS(0xA); | ||
| 64 | }; | ||
| 65 | static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400, | ||
| 66 | "KeyboardSharedMemoryFormat is an invalid size"); | ||
| 67 | |||
| 68 | // This is nn::hid::detail::DigitizerSharedMemoryFormat | ||
| 69 | struct DigitizerSharedMemoryFormat { | ||
| 70 | CommonHeader header; | ||
| 71 | INSERT_PADDING_BYTES(0xFE0); | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000, | ||
| 74 | "DigitizerSharedMemoryFormat is an invalid size"); | ||
| 75 | |||
| 76 | // This is nn::hid::detail::HomeButtonSharedMemoryFormat | ||
| 77 | struct HomeButtonSharedMemoryFormat { | ||
| 78 | CommonHeader header; | ||
| 79 | INSERT_PADDING_BYTES(0x1E0); | ||
| 80 | }; | ||
| 81 | static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, | ||
| 82 | "HomeButtonSharedMemoryFormat is an invalid size"); | ||
| 83 | |||
| 84 | // This is nn::hid::detail::SleepButtonSharedMemoryFormat | ||
| 85 | struct SleepButtonSharedMemoryFormat { | ||
| 86 | CommonHeader header; | ||
| 87 | INSERT_PADDING_BYTES(0x1E0); | ||
| 88 | }; | ||
| 89 | static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, | ||
| 90 | "SleepButtonSharedMemoryFormat is an invalid size"); | ||
| 91 | |||
| 92 | // This is nn::hid::detail::CaptureButtonSharedMemoryFormat | ||
| 93 | struct CaptureButtonSharedMemoryFormat { | ||
| 94 | CommonHeader header; | ||
| 95 | INSERT_PADDING_BYTES(0x1E0); | ||
| 96 | }; | ||
| 97 | static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, | ||
| 98 | "CaptureButtonSharedMemoryFormat is an invalid size"); | ||
| 99 | |||
| 100 | // This is nn::hid::detail::InputDetectorSharedMemoryFormat | ||
| 101 | struct InputDetectorSharedMemoryFormat { | ||
| 102 | CommonHeader header; | ||
| 103 | INSERT_PADDING_BYTES(0x7E0); | ||
| 104 | }; | ||
| 105 | static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800, | ||
| 106 | "InputDetectorSharedMemoryFormat is an invalid size"); | ||
| 107 | |||
| 108 | // This is nn::hid::detail::UniquePadSharedMemoryFormat | ||
| 109 | struct UniquePadSharedMemoryFormat { | ||
| 110 | CommonHeader header; | ||
| 111 | INSERT_PADDING_BYTES(0x3FE0); | ||
| 112 | }; | ||
| 113 | static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000, | ||
| 114 | "UniquePadSharedMemoryFormat is an invalid size"); | ||
| 115 | |||
| 116 | // This is nn::hid::detail::NpadSixAxisSensorLifo | ||
| 117 | struct NpadSixAxisSensorLifo { | ||
| 118 | Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo; | ||
| 119 | }; | ||
| 120 | |||
| 121 | // This is nn::hid::detail::NpadInternalState | ||
| 122 | struct NpadInternalState { | ||
| 123 | Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; | ||
| 124 | NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; | ||
| 125 | NpadFullKeyColorState fullkey_color{}; | ||
| 126 | NpadJoyColorState joycon_color{}; | ||
| 127 | Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{}; | ||
| 128 | Lifo<NPadGenericState, HidEntryCount> handheld_lifo{}; | ||
| 129 | Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{}; | ||
| 130 | Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{}; | ||
| 131 | Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{}; | ||
| 132 | Lifo<NPadGenericState, HidEntryCount> palma_lifo{}; | ||
| 133 | Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{}; | ||
| 134 | NpadSixAxisSensorLifo sixaxis_fullkey_lifo{}; | ||
| 135 | NpadSixAxisSensorLifo sixaxis_handheld_lifo{}; | ||
| 136 | NpadSixAxisSensorLifo sixaxis_dual_left_lifo{}; | ||
| 137 | NpadSixAxisSensorLifo sixaxis_dual_right_lifo{}; | ||
| 138 | NpadSixAxisSensorLifo sixaxis_left_lifo{}; | ||
| 139 | NpadSixAxisSensorLifo sixaxis_right_lifo{}; | ||
| 140 | DeviceType device_type{}; | ||
| 141 | INSERT_PADDING_BYTES(0x4); // Reserved | ||
| 142 | NPadSystemProperties system_properties{}; | ||
| 143 | NpadSystemButtonProperties button_properties{}; | ||
| 144 | Core::HID::NpadBatteryLevel battery_level_dual{}; | ||
| 145 | Core::HID::NpadBatteryLevel battery_level_left{}; | ||
| 146 | Core::HID::NpadBatteryLevel battery_level_right{}; | ||
| 147 | AppletFooterUiAttributes applet_footer_attributes{}; | ||
| 148 | AppletFooterUiType applet_footer_type{AppletFooterUiType::None}; | ||
| 149 | INSERT_PADDING_BYTES(0x5B); // Reserved | ||
| 150 | INSERT_PADDING_BYTES(0x20); // Unknown | ||
| 151 | Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{}; | ||
| 152 | NpadLarkType lark_type_l_and_main{}; | ||
| 153 | NpadLarkType lark_type_r{}; | ||
| 154 | NpadLuciaType lucia_type{}; | ||
| 155 | NpadLagerType lager_type{}; | ||
| 156 | Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties; | ||
| 157 | Core::HID::SixAxisSensorProperties sixaxis_handheld_properties; | ||
| 158 | Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties; | ||
| 159 | Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties; | ||
| 160 | Core::HID::SixAxisSensorProperties sixaxis_left_properties; | ||
| 161 | Core::HID::SixAxisSensorProperties sixaxis_right_properties; | ||
| 162 | }; | ||
| 163 | static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size"); | ||
| 164 | |||
| 165 | // This is nn::hid::detail::NpadSharedMemoryEntry | ||
| 166 | struct NpadSharedMemoryEntry { | ||
| 167 | NpadInternalState internal_state; | ||
| 168 | INSERT_PADDING_BYTES(0xC08); | ||
| 169 | }; | ||
| 170 | static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size"); | ||
| 171 | |||
| 172 | // This is nn::hid::detail::NpadSharedMemoryFormat | ||
| 173 | struct NpadSharedMemoryFormat { | ||
| 174 | std::array<NpadSharedMemoryEntry, MaxSupportedNpadIdTypes> npad_entry; | ||
| 175 | }; | ||
| 176 | static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000, | ||
| 177 | "NpadSharedMemoryFormat is an invalid size"); | ||
| 178 | |||
| 179 | // This is nn::hid::detail::GestureSharedMemoryFormat | ||
| 180 | struct GestureSharedMemoryFormat { | ||
| 181 | // This is nn::hid::detail::GestureLifo | ||
| 182 | Lifo<GestureState, HidEntryCount> gesture_lifo{}; | ||
| 183 | static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); | ||
| 184 | INSERT_PADDING_WORDS(0x3E); | ||
| 185 | }; | ||
| 186 | static_assert(sizeof(GestureSharedMemoryFormat) == 0x800, | ||
| 187 | "GestureSharedMemoryFormat is an invalid size"); | ||
| 188 | |||
| 189 | // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat | ||
| 190 | struct ConsoleSixAxisSensorSharedMemoryFormat { | ||
| 191 | u64 sampling_number{}; | ||
| 192 | bool is_seven_six_axis_sensor_at_rest{}; | ||
| 193 | INSERT_PADDING_BYTES(3); // padding | ||
| 194 | f32 verticalization_error{}; | ||
| 195 | Common::Vec3f gyro_bias{}; | ||
| 196 | INSERT_PADDING_BYTES(4); // padding | ||
| 197 | }; | ||
| 198 | static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20, | ||
| 199 | "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size"); | ||
| 200 | |||
| 201 | // This is nn::hid::detail::SharedMemoryFormat | ||
| 202 | struct SharedMemoryFormat { | ||
| 203 | void Initialize() {} | ||
| 204 | |||
| 205 | DebugPadSharedMemoryFormat debug_pad; | ||
| 206 | TouchScreenSharedMemoryFormat touch_screen; | ||
| 207 | MouseSharedMemoryFormat mouse; | ||
| 208 | KeyboardSharedMemoryFormat keyboard; | ||
| 209 | DigitizerSharedMemoryFormat digitizer; | ||
| 210 | HomeButtonSharedMemoryFormat home_button; | ||
| 211 | SleepButtonSharedMemoryFormat sleep_button; | ||
| 212 | CaptureButtonSharedMemoryFormat capture_button; | ||
| 213 | InputDetectorSharedMemoryFormat input_detector; | ||
| 214 | UniquePadSharedMemoryFormat unique_pad; | ||
| 215 | NpadSharedMemoryFormat npad; | ||
| 216 | GestureSharedMemoryFormat gesture; | ||
| 217 | ConsoleSixAxisSensorSharedMemoryFormat console; | ||
| 218 | INSERT_PADDING_BYTES(0x19E0); | ||
| 219 | MouseSharedMemoryFormat debug_mouse; | ||
| 220 | INSERT_PADDING_BYTES(0x2000); | ||
| 221 | }; | ||
| 222 | static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset"); | ||
| 223 | static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset"); | ||
| 224 | static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset"); | ||
| 225 | static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset"); | ||
| 226 | static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset"); | ||
| 227 | static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset"); | ||
| 228 | static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00, | ||
| 229 | "sleep_button has wrong offset"); | ||
| 230 | static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000, | ||
| 231 | "capture_button has wrong offset"); | ||
| 232 | static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200, | ||
| 233 | "input_detector has wrong offset"); | ||
| 234 | static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset"); | ||
| 235 | static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset"); | ||
| 236 | static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset"); | ||
| 237 | static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset"); | ||
| 238 | static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size"); | ||
| 239 | |||
| 240 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/touch_types.h b/src/core/hle/service/hid/controllers/types/touch_types.h deleted file mode 100644 index efeaa796d..000000000 --- a/src/core/hle/service/hid/controllers/types/touch_types.h +++ /dev/null | |||
| @@ -1,90 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include <array> | ||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/point.h" | ||
| 13 | #include "core/hid/hid_types.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | static constexpr std::size_t MAX_FINGERS = 16; | ||
| 17 | static constexpr size_t MAX_POINTS = 4; | ||
| 18 | |||
| 19 | // This is nn::hid::GestureType | ||
| 20 | enum class GestureType : u32 { | ||
| 21 | Idle, // Nothing touching the screen | ||
| 22 | Complete, // Set at the end of a touch event | ||
| 23 | Cancel, // Set when the number of fingers change | ||
| 24 | Touch, // A finger just touched the screen | ||
| 25 | Press, // Set if last type is touch and the finger hasn't moved | ||
| 26 | Tap, // Fast press then release | ||
| 27 | Pan, // All points moving together across the screen | ||
| 28 | Swipe, // Fast press movement and release of a single point | ||
| 29 | Pinch, // All points moving away/closer to the midpoint | ||
| 30 | Rotate, // All points rotating from the midpoint | ||
| 31 | }; | ||
| 32 | |||
| 33 | // This is nn::hid::GestureDirection | ||
| 34 | enum class GestureDirection : u32 { | ||
| 35 | None, | ||
| 36 | Left, | ||
| 37 | Up, | ||
| 38 | Right, | ||
| 39 | Down, | ||
| 40 | }; | ||
| 41 | |||
| 42 | // This is nn::hid::GestureAttribute | ||
| 43 | struct GestureAttribute { | ||
| 44 | union { | ||
| 45 | u32 raw{}; | ||
| 46 | |||
| 47 | BitField<4, 1, u32> is_new_touch; | ||
| 48 | BitField<8, 1, u32> is_double_tap; | ||
| 49 | }; | ||
| 50 | }; | ||
| 51 | static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); | ||
| 52 | |||
| 53 | // This is nn::hid::GestureState | ||
| 54 | struct GestureState { | ||
| 55 | s64 sampling_number{}; | ||
| 56 | s64 detection_count{}; | ||
| 57 | GestureType type{GestureType::Idle}; | ||
| 58 | GestureDirection direction{GestureDirection::None}; | ||
| 59 | Common::Point<s32> pos{}; | ||
| 60 | Common::Point<s32> delta{}; | ||
| 61 | f32 vel_x{}; | ||
| 62 | f32 vel_y{}; | ||
| 63 | GestureAttribute attributes{}; | ||
| 64 | f32 scale{}; | ||
| 65 | f32 rotation_angle{}; | ||
| 66 | s32 point_count{}; | ||
| 67 | std::array<Common::Point<s32>, 4> points{}; | ||
| 68 | }; | ||
| 69 | static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); | ||
| 70 | |||
| 71 | struct GestureProperties { | ||
| 72 | std::array<Common::Point<s32>, MAX_POINTS> points{}; | ||
| 73 | std::size_t active_points{}; | ||
| 74 | Common::Point<s32> mid_point{}; | ||
| 75 | s64 detection_count{}; | ||
| 76 | u64 delta_time{}; | ||
| 77 | f32 average_distance{}; | ||
| 78 | f32 angle{}; | ||
| 79 | }; | ||
| 80 | |||
| 81 | // This is nn::hid::TouchScreenState | ||
| 82 | struct TouchScreenState { | ||
| 83 | s64 sampling_number{}; | ||
| 84 | s32 entry_count{}; | ||
| 85 | INSERT_PADDING_BYTES(4); // Reserved | ||
| 86 | std::array<Core::HID::TouchState, MAX_FINGERS> states{}; | ||
| 87 | }; | ||
| 88 | static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); | ||
| 89 | |||
| 90 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/unique_pad.cpp b/src/core/hle/service/hid/controllers/unique_pad.cpp deleted file mode 100644 index 6c543031d..000000000 --- a/src/core/hle/service/hid/controllers/unique_pad.cpp +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 7 | #include "core/hle/service/hid/controllers/unique_pad.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | UniquePad::UniquePad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | UniquePad::~UniquePad() = default; | ||
| 14 | |||
| 15 | void UniquePad::OnInit() {} | ||
| 16 | |||
| 17 | void UniquePad::OnRelease() {} | ||
| 18 | |||
| 19 | void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 25 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 26 | |||
| 27 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | auto& header = data->shared_memory_format->capture_button.header; | ||
| 32 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 33 | header.total_entry_count = 17; | ||
| 34 | header.entry_count = 0; | ||
| 35 | header.last_entry_index = 0; | ||
| 36 | } | ||
| 37 | |||
| 38 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/unique_pad.h b/src/core/hle/service/hid/controllers/unique_pad.h deleted file mode 100644 index 966368264..000000000 --- a/src/core/hle/service/hid/controllers/unique_pad.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class UniquePad final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit UniquePad(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~UniquePad() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h deleted file mode 100644 index bb14aa61e..000000000 --- a/src/core/hle/service/hid/errors.h +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | constexpr Result PalmaResultSuccess{ErrorModule::HID, 0}; | ||
| 11 | constexpr Result NpadInvalidHandle{ErrorModule::HID, 100}; | ||
| 12 | constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; | ||
| 13 | |||
| 14 | constexpr Result ResultVibrationNotInitialized{ErrorModule::HID, 121}; | ||
| 15 | constexpr Result ResultVibrationInvalidStyleIndex{ErrorModule::HID, 122}; | ||
| 16 | constexpr Result ResultVibrationInvalidNpadId{ErrorModule::HID, 123}; | ||
| 17 | constexpr Result ResultVibrationDeviceIndexOutOfRange{ErrorModule::HID, 124}; | ||
| 18 | constexpr Result ResultVibrationStrenghtOutOfRange{ErrorModule::HID, 126}; | ||
| 19 | constexpr Result ResultVibrationArraySizeMismatch{ErrorModule::HID, 131}; | ||
| 20 | |||
| 21 | constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423}; | ||
| 22 | |||
| 23 | constexpr Result ResultNfcIsNotReady{ErrorModule::HID, 461}; | ||
| 24 | constexpr Result ResultNfcXcdHandleIsNotInitialized{ErrorModule::HID, 464}; | ||
| 25 | constexpr Result ResultIrSensorIsNotReady{ErrorModule::HID, 501}; | ||
| 26 | constexpr Result ResultMcuIsNotReady{ErrorModule::HID, 541}; | ||
| 27 | |||
| 28 | constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; | ||
| 29 | constexpr Result NpadIsSameType{ErrorModule::HID, 602}; | ||
| 30 | constexpr Result ResultNpadIsNotProController{ErrorModule::HID, 604}; | ||
| 31 | |||
| 32 | constexpr Result ResultInvalidNpadId{ErrorModule::HID, 709}; | ||
| 33 | constexpr Result ResultNpadNotConnected{ErrorModule::HID, 710}; | ||
| 34 | constexpr Result ResultNpadHandlerOverflow{ErrorModule::HID, 711}; | ||
| 35 | constexpr Result ResultNpadHandlerNotInitialized{ErrorModule::HID, 712}; | ||
| 36 | constexpr Result ResultInvalidArraySize{ErrorModule::HID, 715}; | ||
| 37 | constexpr Result ResultUndefinedStyleset{ErrorModule::HID, 716}; | ||
| 38 | constexpr Result ResultMultipleStyleSetSelected{ErrorModule::HID, 717}; | ||
| 39 | |||
| 40 | constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041}; | ||
| 41 | constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042}; | ||
| 42 | constexpr Result ResultSharedMemoryNotInitialized{ErrorModule::HID, 1043}; | ||
| 43 | constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044}; | ||
| 44 | constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046}; | ||
| 45 | constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047}; | ||
| 46 | |||
| 47 | constexpr Result ResultNpadResourceOverflow{ErrorModule::HID, 2001}; | ||
| 48 | constexpr Result ResultNpadResourceNotInitialized{ErrorModule::HID, 2002}; | ||
| 49 | |||
| 50 | constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302}; | ||
| 51 | |||
| 52 | } // namespace Service::HID | ||
| 53 | |||
| 54 | namespace Service::IRS { | ||
| 55 | |||
| 56 | constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78}; | ||
| 57 | constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; | ||
| 58 | |||
| 59 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index bd2873181..fc8a3ab66 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -5,14 +5,14 @@ | |||
| 5 | #include "core/hle/kernel/kernel.h" | 5 | #include "core/hle/kernel/kernel.h" |
| 6 | #include "core/hle/service/hid/hid.h" | 6 | #include "core/hle/service/hid/hid.h" |
| 7 | #include "core/hle/service/hid/hid_debug_server.h" | 7 | #include "core/hle/service/hid/hid_debug_server.h" |
| 8 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 9 | #include "core/hle/service/hid/hid_server.h" | 8 | #include "core/hle/service/hid/hid_server.h" |
| 10 | #include "core/hle/service/hid/hid_system_server.h" | 9 | #include "core/hle/service/hid/hid_system_server.h" |
| 11 | #include "core/hle/service/hid/hidbus.h" | 10 | #include "core/hle/service/hid/hidbus.h" |
| 12 | #include "core/hle/service/hid/irs.h" | 11 | #include "core/hle/service/hid/irs.h" |
| 13 | #include "core/hle/service/hid/resource_manager.h" | ||
| 14 | #include "core/hle/service/hid/xcd.h" | 12 | #include "core/hle/service/hid/xcd.h" |
| 15 | #include "core/hle/service/server_manager.h" | 13 | #include "core/hle/service/server_manager.h" |
| 14 | #include "hid_core/resource_manager.h" | ||
| 15 | #include "hid_core/resources/hid_firmware_settings.h" | ||
| 16 | 16 | ||
| 17 | namespace Service::HID { | 17 | namespace Service::HID { |
| 18 | 18 | ||
diff --git a/src/core/hle/service/hid/hid_debug_server.cpp b/src/core/hle/service/hid/hid_debug_server.cpp index 6294f3dfb..f2a767d37 100644 --- a/src/core/hle/service/hid/hid_debug_server.cpp +++ b/src/core/hle/service/hid/hid_debug_server.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/hid/hid_debug_server.h" | 4 | #include "core/hle/service/hid/hid_debug_server.h" |
| 5 | #include "core/hle/service/hid/resource_manager.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 5 | #include "core/hle/service/ipc_helpers.h" |
| 6 | #include "hid_core/resource_manager.h" | ||
| 7 | 7 | ||
| 8 | namespace Service::HID { | 8 | namespace Service::HID { |
| 9 | 9 | ||
diff --git a/src/core/hle/service/hid/hid_firmware_settings.cpp b/src/core/hle/service/hid/hid_firmware_settings.cpp deleted file mode 100644 index 59bd6825c..000000000 --- a/src/core/hle/service/hid/hid_firmware_settings.cpp +++ /dev/null | |||
| @@ -1,99 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | |||
| 8 | HidFirmwareSettings::HidFirmwareSettings() { | ||
| 9 | LoadSettings(true); | ||
| 10 | } | ||
| 11 | |||
| 12 | void HidFirmwareSettings::Reload() { | ||
| 13 | LoadSettings(true); | ||
| 14 | } | ||
| 15 | |||
| 16 | void HidFirmwareSettings::LoadSettings(bool reload_config) { | ||
| 17 | if (is_initalized && !reload_config) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | |||
| 21 | // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values | ||
| 22 | |||
| 23 | is_debug_pad_enabled = true; | ||
| 24 | is_device_managed = true; | ||
| 25 | is_touch_i2c_managed = is_device_managed; | ||
| 26 | is_future_devices_emulated = false; | ||
| 27 | is_mcu_hardware_error_emulated = false; | ||
| 28 | is_rail_enabled = true; | ||
| 29 | is_firmware_update_failure_emulated = false; | ||
| 30 | is_firmware_update_failure = {}; | ||
| 31 | is_ble_disabled = false; | ||
| 32 | is_dscale_disabled = false; | ||
| 33 | is_handheld_forced = true; | ||
| 34 | features_per_id_disabled = {}; | ||
| 35 | is_touch_firmware_auto_update_disabled = false; | ||
| 36 | is_initalized = true; | ||
| 37 | } | ||
| 38 | |||
| 39 | bool HidFirmwareSettings::IsDebugPadEnabled() { | ||
| 40 | LoadSettings(false); | ||
| 41 | return is_debug_pad_enabled; | ||
| 42 | } | ||
| 43 | |||
| 44 | bool HidFirmwareSettings::IsDeviceManaged() { | ||
| 45 | LoadSettings(false); | ||
| 46 | return is_device_managed; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool HidFirmwareSettings::IsEmulateFutureDevice() { | ||
| 50 | LoadSettings(false); | ||
| 51 | return is_future_devices_emulated; | ||
| 52 | } | ||
| 53 | |||
| 54 | bool HidFirmwareSettings::IsTouchI2cManaged() { | ||
| 55 | LoadSettings(false); | ||
| 56 | return is_touch_i2c_managed; | ||
| 57 | } | ||
| 58 | |||
| 59 | bool HidFirmwareSettings::IsHandheldForced() { | ||
| 60 | LoadSettings(false); | ||
| 61 | return is_handheld_forced; | ||
| 62 | } | ||
| 63 | |||
| 64 | bool HidFirmwareSettings::IsRailEnabled() { | ||
| 65 | LoadSettings(false); | ||
| 66 | return is_rail_enabled; | ||
| 67 | } | ||
| 68 | |||
| 69 | bool HidFirmwareSettings::IsHardwareErrorEmulated() { | ||
| 70 | LoadSettings(false); | ||
| 71 | return is_mcu_hardware_error_emulated; | ||
| 72 | } | ||
| 73 | |||
| 74 | bool HidFirmwareSettings::IsBleDisabled() { | ||
| 75 | LoadSettings(false); | ||
| 76 | return is_ble_disabled; | ||
| 77 | } | ||
| 78 | |||
| 79 | bool HidFirmwareSettings::IsDscaleDisabled() { | ||
| 80 | LoadSettings(false); | ||
| 81 | return is_dscale_disabled; | ||
| 82 | } | ||
| 83 | |||
| 84 | bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() { | ||
| 85 | LoadSettings(false); | ||
| 86 | return is_touch_firmware_auto_update_disabled; | ||
| 87 | } | ||
| 88 | |||
| 89 | HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() { | ||
| 90 | LoadSettings(false); | ||
| 91 | return is_firmware_update_failure; | ||
| 92 | } | ||
| 93 | |||
| 94 | HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() { | ||
| 95 | LoadSettings(false); | ||
| 96 | return features_per_id_disabled; | ||
| 97 | } | ||
| 98 | |||
| 99 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hid_firmware_settings.h b/src/core/hle/service/hid/hid_firmware_settings.h deleted file mode 100644 index 6c10c440b..000000000 --- a/src/core/hle/service/hid/hid_firmware_settings.h +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | /// Loads firmware config from nn::settings::fwdbg | ||
| 11 | class HidFirmwareSettings { | ||
| 12 | public: | ||
| 13 | using FirmwareSetting = std::array<u8, 4>; | ||
| 14 | using FeaturesPerId = std::array<bool, 0xA8>; | ||
| 15 | |||
| 16 | HidFirmwareSettings(); | ||
| 17 | |||
| 18 | void Reload(); | ||
| 19 | void LoadSettings(bool reload_config); | ||
| 20 | |||
| 21 | bool IsDebugPadEnabled(); | ||
| 22 | bool IsDeviceManaged(); | ||
| 23 | bool IsEmulateFutureDevice(); | ||
| 24 | bool IsTouchI2cManaged(); | ||
| 25 | bool IsHandheldForced(); | ||
| 26 | bool IsRailEnabled(); | ||
| 27 | bool IsHardwareErrorEmulated(); | ||
| 28 | bool IsBleDisabled(); | ||
| 29 | bool IsDscaleDisabled(); | ||
| 30 | bool IsTouchAutoUpdateDisabled(); | ||
| 31 | |||
| 32 | FirmwareSetting GetFirmwareUpdateFailure(); | ||
| 33 | FeaturesPerId FeaturesDisabledPerId(); | ||
| 34 | |||
| 35 | private: | ||
| 36 | bool is_initalized{}; | ||
| 37 | |||
| 38 | // Debug settings | ||
| 39 | bool is_debug_pad_enabled{}; | ||
| 40 | bool is_device_managed{}; | ||
| 41 | bool is_touch_i2c_managed{}; | ||
| 42 | bool is_future_devices_emulated{}; | ||
| 43 | bool is_mcu_hardware_error_emulated{}; | ||
| 44 | bool is_rail_enabled{}; | ||
| 45 | bool is_firmware_update_failure_emulated{}; | ||
| 46 | bool is_ble_disabled{}; | ||
| 47 | bool is_dscale_disabled{}; | ||
| 48 | bool is_handheld_forced{}; | ||
| 49 | bool is_touch_firmware_auto_update_disabled{}; | ||
| 50 | FirmwareSetting is_firmware_update_failure{}; | ||
| 51 | FeaturesPerId features_per_id_disabled{}; | ||
| 52 | }; | ||
| 53 | |||
| 54 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index a953c92b3..2ff00d30d 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -5,30 +5,29 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/kernel/k_shared_memory.h" | 8 | #include "core/hle/kernel/k_shared_memory.h" |
| 10 | #include "core/hle/kernel/k_transfer_memory.h" | 9 | #include "core/hle/kernel/k_transfer_memory.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/service/hid/errors.h" | ||
| 13 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 14 | #include "core/hle/service/hid/hid_server.h" | 11 | #include "core/hle/service/hid/hid_server.h" |
| 15 | #include "core/hle/service/hid/hid_util.h" | ||
| 16 | #include "core/hle/service/hid/resource_manager.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | 12 | #include "core/hle/service/ipc_helpers.h" |
| 18 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 19 | 14 | #include "hid_core/hid_result.h" | |
| 20 | #include "core/hle/service/hid/controllers/console_six_axis.h" | 15 | #include "hid_core/hid_util.h" |
| 21 | #include "core/hle/service/hid/controllers/controller_base.h" | 16 | #include "hid_core/resource_manager.h" |
| 22 | #include "core/hle/service/hid/controllers/debug_pad.h" | 17 | #include "hid_core/resources/hid_firmware_settings.h" |
| 23 | #include "core/hle/service/hid/controllers/gesture.h" | 18 | |
| 24 | #include "core/hle/service/hid/controllers/keyboard.h" | 19 | #include "hid_core/resources/controller_base.h" |
| 25 | #include "core/hle/service/hid/controllers/mouse.h" | 20 | #include "hid_core/resources/debug_pad/debug_pad.h" |
| 26 | #include "core/hle/service/hid/controllers/npad.h" | 21 | #include "hid_core/resources/keyboard/keyboard.h" |
| 27 | #include "core/hle/service/hid/controllers/palma.h" | 22 | #include "hid_core/resources/mouse/mouse.h" |
| 28 | #include "core/hle/service/hid/controllers/seven_six_axis.h" | 23 | #include "hid_core/resources/npad/npad.h" |
| 29 | #include "core/hle/service/hid/controllers/six_axis.h" | 24 | #include "hid_core/resources/npad/npad_types.h" |
| 30 | #include "core/hle/service/hid/controllers/touchscreen.h" | 25 | #include "hid_core/resources/palma/palma.h" |
| 31 | #include "core/hle/service/hid/controllers/types/npad_types.h" | 26 | #include "hid_core/resources/six_axis/console_six_axis.h" |
| 27 | #include "hid_core/resources/six_axis/seven_six_axis.h" | ||
| 28 | #include "hid_core/resources/six_axis/six_axis.h" | ||
| 29 | #include "hid_core/resources/touch_screen/gesture.h" | ||
| 30 | #include "hid_core/resources/touch_screen/touch_screen.h" | ||
| 32 | 31 | ||
| 33 | namespace Service::HID { | 32 | namespace Service::HID { |
| 34 | 33 | ||
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 4823de743..027c56025 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp | |||
| @@ -1,15 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hid/hid_core.h" | ||
| 5 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 6 | #include "core/hle/service/hid/controllers/palma.h" | ||
| 7 | #include "core/hle/service/hid/controllers/touchscreen.h" | ||
| 8 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 9 | #include "core/hle/service/hid/errors.h" | ||
| 10 | #include "core/hle/service/hid/hid_system_server.h" | 4 | #include "core/hle/service/hid/hid_system_server.h" |
| 11 | #include "core/hle/service/hid/resource_manager.h" | ||
| 12 | #include "core/hle/service/ipc_helpers.h" | 5 | #include "core/hle/service/ipc_helpers.h" |
| 6 | #include "hid_core/hid_result.h" | ||
| 7 | #include "hid_core/resource_manager.h" | ||
| 8 | #include "hid_core/resources/npad/npad.h" | ||
| 9 | #include "hid_core/resources/npad/npad_types.h" | ||
| 10 | #include "hid_core/resources/palma/palma.h" | ||
| 11 | #include "hid_core/resources/touch_screen/touch_screen.h" | ||
| 13 | 12 | ||
| 14 | namespace Service::HID { | 13 | namespace Service::HID { |
| 15 | 14 | ||
| @@ -270,7 +269,7 @@ void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) { | |||
| 270 | 269 | ||
| 271 | IPC::ResponseBuilder rb{ctx, 3}; | 270 | IPC::ResponseBuilder rb{ctx, 3}; |
| 272 | rb.Push(ResultSuccess); | 271 | rb.Push(ResultSuccess); |
| 273 | rb.PushEnum(system.HIDCore().GetLastActiveController()); | 272 | rb.Push(0); // Dont forget to fix this |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 276 | void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { | 275 | void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/hid_util.h b/src/core/hle/service/hid/hid_util.h deleted file mode 100644 index 6a2ed287a..000000000 --- a/src/core/hle/service/hid/hid_util.h +++ /dev/null | |||
| @@ -1,146 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/service/hid/errors.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) { | ||
| 12 | switch (npad_id) { | ||
| 13 | case Core::HID::NpadIdType::Player1: | ||
| 14 | case Core::HID::NpadIdType::Player2: | ||
| 15 | case Core::HID::NpadIdType::Player3: | ||
| 16 | case Core::HID::NpadIdType::Player4: | ||
| 17 | case Core::HID::NpadIdType::Player5: | ||
| 18 | case Core::HID::NpadIdType::Player6: | ||
| 19 | case Core::HID::NpadIdType::Player7: | ||
| 20 | case Core::HID::NpadIdType::Player8: | ||
| 21 | case Core::HID::NpadIdType::Other: | ||
| 22 | case Core::HID::NpadIdType::Handheld: | ||
| 23 | return true; | ||
| 24 | default: | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) { | ||
| 30 | const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 31 | const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; | ||
| 32 | |||
| 33 | if (!npad_id) { | ||
| 34 | return ResultInvalidNpadId; | ||
| 35 | } | ||
| 36 | if (!device_index) { | ||
| 37 | return NpadDeviceIndexOutOfRange; | ||
| 38 | } | ||
| 39 | |||
| 40 | return ResultSuccess; | ||
| 41 | } | ||
| 42 | |||
| 43 | constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 44 | switch (handle.npad_type) { | ||
| 45 | case Core::HID::NpadStyleIndex::ProController: | ||
| 46 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 47 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 48 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 49 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 50 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 51 | case Core::HID::NpadStyleIndex::N64: | ||
| 52 | case Core::HID::NpadStyleIndex::SystemExt: | ||
| 53 | case Core::HID::NpadStyleIndex::System: | ||
| 54 | // These support vibration | ||
| 55 | break; | ||
| 56 | default: | ||
| 57 | return ResultVibrationInvalidStyleIndex; | ||
| 58 | } | ||
| 59 | |||
| 60 | if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) { | ||
| 61 | return ResultVibrationInvalidNpadId; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) { | ||
| 65 | return ResultVibrationDeviceIndexOutOfRange; | ||
| 66 | } | ||
| 67 | |||
| 68 | return ResultSuccess; | ||
| 69 | } | ||
| 70 | |||
| 71 | /// Converts a Core::HID::NpadIdType to an array index. | ||
| 72 | constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) { | ||
| 73 | switch (npad_id_type) { | ||
| 74 | case Core::HID::NpadIdType::Player1: | ||
| 75 | return 0; | ||
| 76 | case Core::HID::NpadIdType::Player2: | ||
| 77 | return 1; | ||
| 78 | case Core::HID::NpadIdType::Player3: | ||
| 79 | return 2; | ||
| 80 | case Core::HID::NpadIdType::Player4: | ||
| 81 | return 3; | ||
| 82 | case Core::HID::NpadIdType::Player5: | ||
| 83 | return 4; | ||
| 84 | case Core::HID::NpadIdType::Player6: | ||
| 85 | return 5; | ||
| 86 | case Core::HID::NpadIdType::Player7: | ||
| 87 | return 6; | ||
| 88 | case Core::HID::NpadIdType::Player8: | ||
| 89 | return 7; | ||
| 90 | case Core::HID::NpadIdType::Handheld: | ||
| 91 | return 8; | ||
| 92 | case Core::HID::NpadIdType::Other: | ||
| 93 | return 9; | ||
| 94 | default: | ||
| 95 | return 8; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | /// Converts an array index to a Core::HID::NpadIdType | ||
| 100 | constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) { | ||
| 101 | switch (index) { | ||
| 102 | case 0: | ||
| 103 | return Core::HID::NpadIdType::Player1; | ||
| 104 | case 1: | ||
| 105 | return Core::HID::NpadIdType::Player2; | ||
| 106 | case 2: | ||
| 107 | return Core::HID::NpadIdType::Player3; | ||
| 108 | case 3: | ||
| 109 | return Core::HID::NpadIdType::Player4; | ||
| 110 | case 4: | ||
| 111 | return Core::HID::NpadIdType::Player5; | ||
| 112 | case 5: | ||
| 113 | return Core::HID::NpadIdType::Player6; | ||
| 114 | case 6: | ||
| 115 | return Core::HID::NpadIdType::Player7; | ||
| 116 | case 7: | ||
| 117 | return Core::HID::NpadIdType::Player8; | ||
| 118 | case 8: | ||
| 119 | return Core::HID::NpadIdType::Handheld; | ||
| 120 | case 9: | ||
| 121 | return Core::HID::NpadIdType::Other; | ||
| 122 | default: | ||
| 123 | return Core::HID::NpadIdType::Invalid; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) { | ||
| 128 | switch (index) { | ||
| 129 | case 0: | ||
| 130 | return Core::HID::NpadStyleSet::Fullkey; | ||
| 131 | case 1: | ||
| 132 | return Core::HID::NpadStyleSet::Handheld; | ||
| 133 | case 2: | ||
| 134 | return Core::HID::NpadStyleSet::JoyDual; | ||
| 135 | case 3: | ||
| 136 | return Core::HID::NpadStyleSet::JoyLeft; | ||
| 137 | case 4: | ||
| 138 | return Core::HID::NpadStyleSet::JoyRight; | ||
| 139 | case 5: | ||
| 140 | return Core::HID::NpadStyleSet::Palma; | ||
| 141 | default: | ||
| 142 | return Core::HID::NpadStyleSet::None; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index ffa7e144d..46f503d38 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp | |||
| @@ -5,18 +5,18 @@ | |||
| 5 | #include "common/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 11 | #include "core/hle/kernel/k_shared_memory.h" | 10 | #include "core/hle/kernel/k_shared_memory.h" |
| 12 | #include "core/hle/kernel/k_transfer_memory.h" | 11 | #include "core/hle/kernel/k_transfer_memory.h" |
| 13 | #include "core/hle/service/hid/hidbus.h" | 12 | #include "core/hle/service/hid/hidbus.h" |
| 14 | #include "core/hle/service/hid/hidbus/ringcon.h" | ||
| 15 | #include "core/hle/service/hid/hidbus/starlink.h" | ||
| 16 | #include "core/hle/service/hid/hidbus/stubbed.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | 13 | #include "core/hle/service/ipc_helpers.h" |
| 18 | #include "core/hle/service/service.h" | 14 | #include "core/hle/service/service.h" |
| 19 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 16 | #include "hid_core/hid_types.h" | ||
| 17 | #include "hid_core/hidbus/ringcon.h" | ||
| 18 | #include "hid_core/hidbus/starlink.h" | ||
| 19 | #include "hid_core/hidbus/stubbed.h" | ||
| 20 | 20 | ||
| 21 | namespace Service::HID { | 21 | namespace Service::HID { |
| 22 | // (15ms, 66Hz) | 22 | // (15ms, 66Hz) |
diff --git a/src/core/hle/service/hid/hidbus.h b/src/core/hle/service/hid/hidbus.h index 85a1df133..05f62f634 100644 --- a/src/core/hle/service/hid/hidbus.h +++ b/src/core/hle/service/hid/hidbus.h | |||
| @@ -5,9 +5,9 @@ | |||
| 5 | 5 | ||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | 7 | ||
| 8 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 9 | #include "core/hle/service/kernel_helpers.h" | 8 | #include "core/hle/service/kernel_helpers.h" |
| 10 | #include "core/hle/service/service.h" | 9 | #include "core/hle/service/service.h" |
| 10 | #include "hid_core/hidbus/hidbus_base.h" | ||
| 11 | 11 | ||
| 12 | namespace Core::Timing { | 12 | namespace Core::Timing { |
| 13 | struct EventType; | 13 | struct EventType; |
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp deleted file mode 100644 index 8c44f93e8..000000000 --- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp +++ /dev/null | |||
| @@ -1,73 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/hid_core.h" | ||
| 5 | #include "core/hle/kernel/k_event.h" | ||
| 6 | #include "core/hle/kernel/k_readable_event.h" | ||
| 7 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 8 | #include "core/hle/service/kernel_helpers.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | HidbusBase::HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_) | ||
| 13 | : system(system_), service_context(service_context_) { | ||
| 14 | send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent"); | ||
| 15 | } | ||
| 16 | |||
| 17 | HidbusBase::~HidbusBase() { | ||
| 18 | service_context.CloseEvent(send_command_async_event); | ||
| 19 | }; | ||
| 20 | |||
| 21 | void HidbusBase::ActivateDevice() { | ||
| 22 | if (is_activated) { | ||
| 23 | return; | ||
| 24 | } | ||
| 25 | is_activated = true; | ||
| 26 | OnInit(); | ||
| 27 | } | ||
| 28 | |||
| 29 | void HidbusBase::DeactivateDevice() { | ||
| 30 | if (is_activated) { | ||
| 31 | OnRelease(); | ||
| 32 | } | ||
| 33 | is_activated = false; | ||
| 34 | } | ||
| 35 | |||
| 36 | bool HidbusBase::IsDeviceActivated() const { | ||
| 37 | return is_activated; | ||
| 38 | } | ||
| 39 | |||
| 40 | void HidbusBase::Enable(bool enable) { | ||
| 41 | device_enabled = enable; | ||
| 42 | } | ||
| 43 | |||
| 44 | bool HidbusBase::IsEnabled() const { | ||
| 45 | return device_enabled; | ||
| 46 | } | ||
| 47 | |||
| 48 | bool HidbusBase::IsPollingMode() const { | ||
| 49 | return polling_mode_enabled; | ||
| 50 | } | ||
| 51 | |||
| 52 | JoyPollingMode HidbusBase::GetPollingMode() const { | ||
| 53 | return polling_mode; | ||
| 54 | } | ||
| 55 | |||
| 56 | void HidbusBase::SetPollingMode(JoyPollingMode mode) { | ||
| 57 | polling_mode = mode; | ||
| 58 | polling_mode_enabled = true; | ||
| 59 | } | ||
| 60 | |||
| 61 | void HidbusBase::DisablePollingMode() { | ||
| 62 | polling_mode_enabled = false; | ||
| 63 | } | ||
| 64 | |||
| 65 | void HidbusBase::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { | ||
| 66 | transfer_memory = t_mem; | ||
| 67 | } | ||
| 68 | |||
| 69 | Kernel::KReadableEvent& HidbusBase::GetSendCommandAsycEvent() const { | ||
| 70 | return send_command_async_event->GetReadableEvent(); | ||
| 71 | } | ||
| 72 | |||
| 73 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h deleted file mode 100644 index ec41684e1..000000000 --- a/src/core/hle/service/hid/hidbus/hidbus_base.h +++ /dev/null | |||
| @@ -1,183 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | #include "common/typed_address.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Kernel { | ||
| 16 | class KEvent; | ||
| 17 | class KReadableEvent; | ||
| 18 | } // namespace Kernel | ||
| 19 | |||
| 20 | namespace Service::KernelHelpers { | ||
| 21 | class ServiceContext; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace Service::HID { | ||
| 25 | |||
| 26 | // This is nn::hidbus::JoyPollingMode | ||
| 27 | enum class JoyPollingMode : u32 { | ||
| 28 | SixAxisSensorDisable, | ||
| 29 | SixAxisSensorEnable, | ||
| 30 | ButtonOnly, | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct DataAccessorHeader { | ||
| 34 | Result result{ResultUnknown}; | ||
| 35 | INSERT_PADDING_WORDS(0x1); | ||
| 36 | std::array<u8, 0x18> unused{}; | ||
| 37 | u64 latest_entry{}; | ||
| 38 | u64 total_entries{}; | ||
| 39 | }; | ||
| 40 | static_assert(sizeof(DataAccessorHeader) == 0x30, "DataAccessorHeader is an invalid size"); | ||
| 41 | |||
| 42 | struct JoyDisableSixAxisPollingData { | ||
| 43 | std::array<u8, 0x26> data; | ||
| 44 | u8 out_size; | ||
| 45 | INSERT_PADDING_BYTES(0x1); | ||
| 46 | u64 sampling_number; | ||
| 47 | }; | ||
| 48 | static_assert(sizeof(JoyDisableSixAxisPollingData) == 0x30, | ||
| 49 | "JoyDisableSixAxisPollingData is an invalid size"); | ||
| 50 | |||
| 51 | struct JoyEnableSixAxisPollingData { | ||
| 52 | std::array<u8, 0x8> data; | ||
| 53 | u8 out_size; | ||
| 54 | INSERT_PADDING_BYTES(0x7); | ||
| 55 | u64 sampling_number; | ||
| 56 | }; | ||
| 57 | static_assert(sizeof(JoyEnableSixAxisPollingData) == 0x18, | ||
| 58 | "JoyEnableSixAxisPollingData is an invalid size"); | ||
| 59 | |||
| 60 | struct JoyButtonOnlyPollingData { | ||
| 61 | std::array<u8, 0x2c> data; | ||
| 62 | u8 out_size; | ||
| 63 | INSERT_PADDING_BYTES(0x3); | ||
| 64 | u64 sampling_number; | ||
| 65 | }; | ||
| 66 | static_assert(sizeof(JoyButtonOnlyPollingData) == 0x38, | ||
| 67 | "JoyButtonOnlyPollingData is an invalid size"); | ||
| 68 | |||
| 69 | struct JoyDisableSixAxisPollingEntry { | ||
| 70 | u64 sampling_number; | ||
| 71 | JoyDisableSixAxisPollingData polling_data; | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(JoyDisableSixAxisPollingEntry) == 0x38, | ||
| 74 | "JoyDisableSixAxisPollingEntry is an invalid size"); | ||
| 75 | |||
| 76 | struct JoyEnableSixAxisPollingEntry { | ||
| 77 | u64 sampling_number; | ||
| 78 | JoyEnableSixAxisPollingData polling_data; | ||
| 79 | }; | ||
| 80 | static_assert(sizeof(JoyEnableSixAxisPollingEntry) == 0x20, | ||
| 81 | "JoyEnableSixAxisPollingEntry is an invalid size"); | ||
| 82 | |||
| 83 | struct JoyButtonOnlyPollingEntry { | ||
| 84 | u64 sampling_number; | ||
| 85 | JoyButtonOnlyPollingData polling_data; | ||
| 86 | }; | ||
| 87 | static_assert(sizeof(JoyButtonOnlyPollingEntry) == 0x40, | ||
| 88 | "JoyButtonOnlyPollingEntry is an invalid size"); | ||
| 89 | |||
| 90 | struct JoyDisableSixAxisDataAccessor { | ||
| 91 | DataAccessorHeader header{}; | ||
| 92 | std::array<JoyDisableSixAxisPollingEntry, 0xb> entries{}; | ||
| 93 | }; | ||
| 94 | static_assert(sizeof(JoyDisableSixAxisDataAccessor) == 0x298, | ||
| 95 | "JoyDisableSixAxisDataAccessor is an invalid size"); | ||
| 96 | |||
| 97 | struct JoyEnableSixAxisDataAccessor { | ||
| 98 | DataAccessorHeader header{}; | ||
| 99 | std::array<JoyEnableSixAxisPollingEntry, 0xb> entries{}; | ||
| 100 | }; | ||
| 101 | static_assert(sizeof(JoyEnableSixAxisDataAccessor) == 0x190, | ||
| 102 | "JoyEnableSixAxisDataAccessor is an invalid size"); | ||
| 103 | |||
| 104 | struct ButtonOnlyPollingDataAccessor { | ||
| 105 | DataAccessorHeader header; | ||
| 106 | std::array<JoyButtonOnlyPollingEntry, 0xb> entries; | ||
| 107 | }; | ||
| 108 | static_assert(sizeof(ButtonOnlyPollingDataAccessor) == 0x2F0, | ||
| 109 | "ButtonOnlyPollingDataAccessor is an invalid size"); | ||
| 110 | |||
| 111 | class HidbusBase { | ||
| 112 | public: | ||
| 113 | explicit HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 114 | virtual ~HidbusBase(); | ||
| 115 | |||
| 116 | void ActivateDevice(); | ||
| 117 | |||
| 118 | void DeactivateDevice(); | ||
| 119 | |||
| 120 | bool IsDeviceActivated() const; | ||
| 121 | |||
| 122 | // Enables/disables the device | ||
| 123 | void Enable(bool enable); | ||
| 124 | |||
| 125 | // returns true if device is enabled | ||
| 126 | bool IsEnabled() const; | ||
| 127 | |||
| 128 | // returns true if polling mode is enabled | ||
| 129 | bool IsPollingMode() const; | ||
| 130 | |||
| 131 | // returns polling mode | ||
| 132 | JoyPollingMode GetPollingMode() const; | ||
| 133 | |||
| 134 | // Sets and enables JoyPollingMode | ||
| 135 | void SetPollingMode(JoyPollingMode mode); | ||
| 136 | |||
| 137 | // Disables JoyPollingMode | ||
| 138 | void DisablePollingMode(); | ||
| 139 | |||
| 140 | // Called on EnableJoyPollingReceiveMode | ||
| 141 | void SetTransferMemoryAddress(Common::ProcessAddress t_mem); | ||
| 142 | |||
| 143 | Kernel::KReadableEvent& GetSendCommandAsycEvent() const; | ||
| 144 | |||
| 145 | virtual void OnInit() {} | ||
| 146 | |||
| 147 | virtual void OnRelease() {} | ||
| 148 | |||
| 149 | // Updates device transfer memory | ||
| 150 | virtual void OnUpdate() {} | ||
| 151 | |||
| 152 | // Returns the device ID of the joycon | ||
| 153 | virtual u8 GetDeviceId() const { | ||
| 154 | return {}; | ||
| 155 | } | ||
| 156 | |||
| 157 | // Assigns a command from data | ||
| 158 | virtual bool SetCommand(std::span<const u8> data) { | ||
| 159 | return {}; | ||
| 160 | } | ||
| 161 | |||
| 162 | // Returns a reply from a command | ||
| 163 | virtual std::vector<u8> GetReply() const { | ||
| 164 | return {}; | ||
| 165 | } | ||
| 166 | |||
| 167 | protected: | ||
| 168 | bool is_activated{}; | ||
| 169 | bool device_enabled{}; | ||
| 170 | bool polling_mode_enabled{}; | ||
| 171 | JoyPollingMode polling_mode = {}; | ||
| 172 | // TODO(German77): All data accessors need to be replaced with a ring lifo object | ||
| 173 | JoyDisableSixAxisDataAccessor disable_sixaxis_data{}; | ||
| 174 | JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; | ||
| 175 | ButtonOnlyPollingDataAccessor button_only_data{}; | ||
| 176 | |||
| 177 | Common::ProcessAddress transfer_memory{}; | ||
| 178 | |||
| 179 | Core::System& system; | ||
| 180 | Kernel::KEvent* send_command_async_event; | ||
| 181 | KernelHelpers::ServiceContext& service_context; | ||
| 182 | }; | ||
| 183 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp deleted file mode 100644 index 378108012..000000000 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ /dev/null | |||
| @@ -1,292 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hid/emulated_controller.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 8 | #include "core/hle/kernel/k_readable_event.h" | ||
| 9 | #include "core/hle/service/hid/hidbus/ringcon.h" | ||
| 10 | #include "core/memory.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | RingController::RingController(Core::System& system_, | ||
| 15 | KernelHelpers::ServiceContext& service_context_) | ||
| 16 | : HidbusBase(system_, service_context_) { | ||
| 17 | input = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); | ||
| 18 | } | ||
| 19 | |||
| 20 | RingController::~RingController() = default; | ||
| 21 | |||
| 22 | void RingController::OnInit() { | ||
| 23 | input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, | ||
| 24 | Common::Input::PollingMode::Ring); | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | |||
| 28 | void RingController::OnRelease() { | ||
| 29 | input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, | ||
| 30 | Common::Input::PollingMode::Active); | ||
| 31 | return; | ||
| 32 | }; | ||
| 33 | |||
| 34 | void RingController::OnUpdate() { | ||
| 35 | if (!is_activated) { | ||
| 36 | return; | ||
| 37 | } | ||
| 38 | |||
| 39 | if (!device_enabled) { | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | |||
| 43 | if (!polling_mode_enabled || transfer_memory == 0) { | ||
| 44 | return; | ||
| 45 | } | ||
| 46 | |||
| 47 | // TODO: Increment multitasking counters from motion and sensor data | ||
| 48 | |||
| 49 | switch (polling_mode) { | ||
| 50 | case JoyPollingMode::SixAxisSensorEnable: { | ||
| 51 | enable_sixaxis_data.header.total_entries = 10; | ||
| 52 | enable_sixaxis_data.header.result = ResultSuccess; | ||
| 53 | const auto& last_entry = | ||
| 54 | enable_sixaxis_data.entries[enable_sixaxis_data.header.latest_entry]; | ||
| 55 | |||
| 56 | enable_sixaxis_data.header.latest_entry = | ||
| 57 | (enable_sixaxis_data.header.latest_entry + 1) % 10; | ||
| 58 | auto& curr_entry = enable_sixaxis_data.entries[enable_sixaxis_data.header.latest_entry]; | ||
| 59 | |||
| 60 | curr_entry.sampling_number = last_entry.sampling_number + 1; | ||
| 61 | curr_entry.polling_data.sampling_number = curr_entry.sampling_number; | ||
| 62 | |||
| 63 | const RingConData ringcon_value = GetSensorValue(); | ||
| 64 | curr_entry.polling_data.out_size = sizeof(ringcon_value); | ||
| 65 | std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value)); | ||
| 66 | |||
| 67 | system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data, | ||
| 68 | sizeof(enable_sixaxis_data)); | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | default: | ||
| 72 | LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | RingController::RingConData RingController::GetSensorValue() const { | ||
| 78 | RingConData ringcon_sensor_value{ | ||
| 79 | .status = DataValid::Valid, | ||
| 80 | .data = 0, | ||
| 81 | }; | ||
| 82 | |||
| 83 | const f32 force_value = input->GetRingSensorForce().force * range; | ||
| 84 | ringcon_sensor_value.data = static_cast<s16>(force_value) + idle_value; | ||
| 85 | |||
| 86 | return ringcon_sensor_value; | ||
| 87 | } | ||
| 88 | |||
| 89 | u8 RingController::GetDeviceId() const { | ||
| 90 | return device_id; | ||
| 91 | } | ||
| 92 | |||
| 93 | std::vector<u8> RingController::GetReply() const { | ||
| 94 | const RingConCommands current_command = command; | ||
| 95 | |||
| 96 | switch (current_command) { | ||
| 97 | case RingConCommands::GetFirmwareVersion: | ||
| 98 | return GetFirmwareVersionReply(); | ||
| 99 | case RingConCommands::ReadId: | ||
| 100 | return GetReadIdReply(); | ||
| 101 | case RingConCommands::c20105: | ||
| 102 | return GetC020105Reply(); | ||
| 103 | case RingConCommands::ReadUnkCal: | ||
| 104 | return GetReadUnkCalReply(); | ||
| 105 | case RingConCommands::ReadFactoryCal: | ||
| 106 | return GetReadFactoryCalReply(); | ||
| 107 | case RingConCommands::ReadUserCal: | ||
| 108 | return GetReadUserCalReply(); | ||
| 109 | case RingConCommands::ReadRepCount: | ||
| 110 | return GetReadRepCountReply(); | ||
| 111 | case RingConCommands::ReadTotalPushCount: | ||
| 112 | return GetReadTotalPushCountReply(); | ||
| 113 | case RingConCommands::ResetRepCount: | ||
| 114 | return GetResetRepCountReply(); | ||
| 115 | case RingConCommands::SaveCalData: | ||
| 116 | return GetSaveDataReply(); | ||
| 117 | default: | ||
| 118 | return GetErrorReply(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | bool RingController::SetCommand(std::span<const u8> data) { | ||
| 123 | if (data.size() < 4) { | ||
| 124 | LOG_ERROR(Service_HID, "Command size not supported {}", data.size()); | ||
| 125 | command = RingConCommands::Error; | ||
| 126 | return false; | ||
| 127 | } | ||
| 128 | |||
| 129 | std::memcpy(&command, data.data(), sizeof(RingConCommands)); | ||
| 130 | |||
| 131 | switch (command) { | ||
| 132 | case RingConCommands::GetFirmwareVersion: | ||
| 133 | case RingConCommands::ReadId: | ||
| 134 | case RingConCommands::c20105: | ||
| 135 | case RingConCommands::ReadUnkCal: | ||
| 136 | case RingConCommands::ReadFactoryCal: | ||
| 137 | case RingConCommands::ReadUserCal: | ||
| 138 | case RingConCommands::ReadRepCount: | ||
| 139 | case RingConCommands::ReadTotalPushCount: | ||
| 140 | ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); | ||
| 141 | send_command_async_event->Signal(); | ||
| 142 | return true; | ||
| 143 | case RingConCommands::ResetRepCount: | ||
| 144 | ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); | ||
| 145 | total_rep_count = 0; | ||
| 146 | send_command_async_event->Signal(); | ||
| 147 | return true; | ||
| 148 | case RingConCommands::SaveCalData: { | ||
| 149 | ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); | ||
| 150 | |||
| 151 | SaveCalData save_info{}; | ||
| 152 | std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); | ||
| 153 | user_calibration = save_info.calibration; | ||
| 154 | send_command_async_event->Signal(); | ||
| 155 | return true; | ||
| 156 | } | ||
| 157 | default: | ||
| 158 | LOG_ERROR(Service_HID, "Command not implemented {}", command); | ||
| 159 | command = RingConCommands::Error; | ||
| 160 | // Signal a reply to avoid softlocking the game | ||
| 161 | send_command_async_event->Signal(); | ||
| 162 | return false; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | std::vector<u8> RingController::GetFirmwareVersionReply() const { | ||
| 167 | const FirmwareVersionReply reply{ | ||
| 168 | .status = DataValid::Valid, | ||
| 169 | .firmware = version, | ||
| 170 | }; | ||
| 171 | |||
| 172 | return GetDataVector(reply); | ||
| 173 | } | ||
| 174 | |||
| 175 | std::vector<u8> RingController::GetReadIdReply() const { | ||
| 176 | // The values are hardcoded from a real joycon | ||
| 177 | const ReadIdReply reply{ | ||
| 178 | .status = DataValid::Valid, | ||
| 179 | .id_l_x0 = 8, | ||
| 180 | .id_l_x0_2 = 41, | ||
| 181 | .id_l_x4 = 22294, | ||
| 182 | .id_h_x0 = 19777, | ||
| 183 | .id_h_x0_2 = 13621, | ||
| 184 | .id_h_x4 = 8245, | ||
| 185 | }; | ||
| 186 | |||
| 187 | return GetDataVector(reply); | ||
| 188 | } | ||
| 189 | |||
| 190 | std::vector<u8> RingController::GetC020105Reply() const { | ||
| 191 | const Cmd020105Reply reply{ | ||
| 192 | .status = DataValid::Valid, | ||
| 193 | .data = 1, | ||
| 194 | }; | ||
| 195 | |||
| 196 | return GetDataVector(reply); | ||
| 197 | } | ||
| 198 | |||
| 199 | std::vector<u8> RingController::GetReadUnkCalReply() const { | ||
| 200 | const ReadUnkCalReply reply{ | ||
| 201 | .status = DataValid::Valid, | ||
| 202 | .data = 0, | ||
| 203 | }; | ||
| 204 | |||
| 205 | return GetDataVector(reply); | ||
| 206 | } | ||
| 207 | |||
| 208 | std::vector<u8> RingController::GetReadFactoryCalReply() const { | ||
| 209 | const ReadFactoryCalReply reply{ | ||
| 210 | .status = DataValid::Valid, | ||
| 211 | .calibration = factory_calibration, | ||
| 212 | }; | ||
| 213 | |||
| 214 | return GetDataVector(reply); | ||
| 215 | } | ||
| 216 | |||
| 217 | std::vector<u8> RingController::GetReadUserCalReply() const { | ||
| 218 | const ReadUserCalReply reply{ | ||
| 219 | .status = DataValid::Valid, | ||
| 220 | .calibration = user_calibration, | ||
| 221 | }; | ||
| 222 | |||
| 223 | return GetDataVector(reply); | ||
| 224 | } | ||
| 225 | |||
| 226 | std::vector<u8> RingController::GetReadRepCountReply() const { | ||
| 227 | const GetThreeByteReply reply{ | ||
| 228 | .status = DataValid::Valid, | ||
| 229 | .data = {total_rep_count, 0, 0}, | ||
| 230 | .crc = GetCrcValue({total_rep_count, 0, 0, 0}), | ||
| 231 | }; | ||
| 232 | |||
| 233 | return GetDataVector(reply); | ||
| 234 | } | ||
| 235 | |||
| 236 | std::vector<u8> RingController::GetReadTotalPushCountReply() const { | ||
| 237 | const GetThreeByteReply reply{ | ||
| 238 | .status = DataValid::Valid, | ||
| 239 | .data = {total_push_count, 0, 0}, | ||
| 240 | .crc = GetCrcValue({total_push_count, 0, 0, 0}), | ||
| 241 | }; | ||
| 242 | |||
| 243 | return GetDataVector(reply); | ||
| 244 | } | ||
| 245 | |||
| 246 | std::vector<u8> RingController::GetResetRepCountReply() const { | ||
| 247 | return GetReadRepCountReply(); | ||
| 248 | } | ||
| 249 | |||
| 250 | std::vector<u8> RingController::GetSaveDataReply() const { | ||
| 251 | const StatusReply reply{ | ||
| 252 | .status = DataValid::Valid, | ||
| 253 | }; | ||
| 254 | |||
| 255 | return GetDataVector(reply); | ||
| 256 | } | ||
| 257 | |||
| 258 | std::vector<u8> RingController::GetErrorReply() const { | ||
| 259 | const ErrorReply reply{ | ||
| 260 | .status = DataValid::BadCRC, | ||
| 261 | }; | ||
| 262 | |||
| 263 | return GetDataVector(reply); | ||
| 264 | } | ||
| 265 | |||
| 266 | u8 RingController::GetCrcValue(const std::vector<u8>& data) const { | ||
| 267 | u8 crc = 0; | ||
| 268 | for (std::size_t index = 0; index < data.size(); index++) { | ||
| 269 | for (u8 i = 0x80; i > 0; i >>= 1) { | ||
| 270 | bool bit = (crc & 0x80) != 0; | ||
| 271 | if ((data[index] & i) != 0) { | ||
| 272 | bit = !bit; | ||
| 273 | } | ||
| 274 | crc <<= 1; | ||
| 275 | if (bit) { | ||
| 276 | crc ^= 0x8d; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | } | ||
| 280 | return crc; | ||
| 281 | } | ||
| 282 | |||
| 283 | template <typename T> | ||
| 284 | std::vector<u8> RingController::GetDataVector(const T& reply) const { | ||
| 285 | static_assert(std::is_trivially_copyable_v<T>); | ||
| 286 | std::vector<u8> data; | ||
| 287 | data.resize(sizeof(reply)); | ||
| 288 | std::memcpy(data.data(), &reply, sizeof(reply)); | ||
| 289 | return data; | ||
| 290 | } | ||
| 291 | |||
| 292 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h deleted file mode 100644 index f42f3ea41..000000000 --- a/src/core/hle/service/hid/hidbus/ringcon.h +++ /dev/null | |||
| @@ -1,253 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedController; | ||
| 14 | } // namespace Core::HID | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | |||
| 18 | class RingController final : public HidbusBase { | ||
| 19 | public: | ||
| 20 | explicit RingController(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 21 | ~RingController() override; | ||
| 22 | |||
| 23 | void OnInit() override; | ||
| 24 | |||
| 25 | void OnRelease() override; | ||
| 26 | |||
| 27 | // Updates ringcon transfer memory | ||
| 28 | void OnUpdate() override; | ||
| 29 | |||
| 30 | // Returns the device ID of the joycon | ||
| 31 | u8 GetDeviceId() const override; | ||
| 32 | |||
| 33 | // Assigns a command from data | ||
| 34 | bool SetCommand(std::span<const u8> data) override; | ||
| 35 | |||
| 36 | // Returns a reply from a command | ||
| 37 | std::vector<u8> GetReply() const override; | ||
| 38 | |||
| 39 | private: | ||
| 40 | // These values are obtained from a real ring controller | ||
| 41 | static constexpr s16 idle_value = 2280; | ||
| 42 | static constexpr s16 idle_deadzone = 120; | ||
| 43 | static constexpr s16 range = 2500; | ||
| 44 | |||
| 45 | // Most missing command names are leftovers from other firmware versions | ||
| 46 | enum class RingConCommands : u32 { | ||
| 47 | GetFirmwareVersion = 0x00020000, | ||
| 48 | ReadId = 0x00020100, | ||
| 49 | JoyPolling = 0x00020101, | ||
| 50 | Unknown1 = 0x00020104, | ||
| 51 | c20105 = 0x00020105, | ||
| 52 | Unknown2 = 0x00020204, | ||
| 53 | Unknown3 = 0x00020304, | ||
| 54 | Unknown4 = 0x00020404, | ||
| 55 | ReadUnkCal = 0x00020504, | ||
| 56 | ReadFactoryCal = 0x00020A04, | ||
| 57 | Unknown5 = 0x00021104, | ||
| 58 | Unknown6 = 0x00021204, | ||
| 59 | Unknown7 = 0x00021304, | ||
| 60 | ReadUserCal = 0x00021A04, | ||
| 61 | ReadRepCount = 0x00023104, | ||
| 62 | ReadTotalPushCount = 0x00023204, | ||
| 63 | ResetRepCount = 0x04013104, | ||
| 64 | Unknown8 = 0x04011104, | ||
| 65 | Unknown9 = 0x04011204, | ||
| 66 | Unknown10 = 0x04011304, | ||
| 67 | SaveCalData = 0x10011A04, | ||
| 68 | Error = 0xFFFFFFFF, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum class DataValid : u32 { | ||
| 72 | Valid, | ||
| 73 | BadCRC, | ||
| 74 | Cal, | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct FirmwareVersion { | ||
| 78 | u8 sub; | ||
| 79 | u8 main; | ||
| 80 | }; | ||
| 81 | static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid size"); | ||
| 82 | |||
| 83 | struct FactoryCalibration { | ||
| 84 | s32_le os_max; | ||
| 85 | s32_le hk_max; | ||
| 86 | s32_le zero_min; | ||
| 87 | s32_le zero_max; | ||
| 88 | }; | ||
| 89 | static_assert(sizeof(FactoryCalibration) == 0x10, "FactoryCalibration is an invalid size"); | ||
| 90 | |||
| 91 | struct CalibrationValue { | ||
| 92 | s16 value; | ||
| 93 | u16 crc; | ||
| 94 | }; | ||
| 95 | static_assert(sizeof(CalibrationValue) == 0x4, "CalibrationValue is an invalid size"); | ||
| 96 | |||
| 97 | struct UserCalibration { | ||
| 98 | CalibrationValue os_max; | ||
| 99 | CalibrationValue hk_max; | ||
| 100 | CalibrationValue zero; | ||
| 101 | }; | ||
| 102 | static_assert(sizeof(UserCalibration) == 0xC, "UserCalibration is an invalid size"); | ||
| 103 | |||
| 104 | struct SaveCalData { | ||
| 105 | RingConCommands command; | ||
| 106 | UserCalibration calibration; | ||
| 107 | INSERT_PADDING_BYTES_NOINIT(4); | ||
| 108 | }; | ||
| 109 | static_assert(sizeof(SaveCalData) == 0x14, "SaveCalData is an invalid size"); | ||
| 110 | static_assert(std::is_trivially_copyable_v<SaveCalData>, | ||
| 111 | "SaveCalData must be trivially copyable"); | ||
| 112 | |||
| 113 | struct FirmwareVersionReply { | ||
| 114 | DataValid status; | ||
| 115 | FirmwareVersion firmware; | ||
| 116 | INSERT_PADDING_BYTES(0x2); | ||
| 117 | }; | ||
| 118 | static_assert(sizeof(FirmwareVersionReply) == 0x8, "FirmwareVersionReply is an invalid size"); | ||
| 119 | |||
| 120 | struct Cmd020105Reply { | ||
| 121 | DataValid status; | ||
| 122 | u8 data; | ||
| 123 | INSERT_PADDING_BYTES(0x3); | ||
| 124 | }; | ||
| 125 | static_assert(sizeof(Cmd020105Reply) == 0x8, "Cmd020105Reply is an invalid size"); | ||
| 126 | |||
| 127 | struct StatusReply { | ||
| 128 | DataValid status; | ||
| 129 | }; | ||
| 130 | static_assert(sizeof(StatusReply) == 0x4, "StatusReply is an invalid size"); | ||
| 131 | |||
| 132 | struct GetThreeByteReply { | ||
| 133 | DataValid status; | ||
| 134 | std::array<u8, 3> data; | ||
| 135 | u8 crc; | ||
| 136 | }; | ||
| 137 | static_assert(sizeof(GetThreeByteReply) == 0x8, "GetThreeByteReply is an invalid size"); | ||
| 138 | |||
| 139 | struct ReadUnkCalReply { | ||
| 140 | DataValid status; | ||
| 141 | u16 data; | ||
| 142 | INSERT_PADDING_BYTES(0x2); | ||
| 143 | }; | ||
| 144 | static_assert(sizeof(ReadUnkCalReply) == 0x8, "ReadUnkCalReply is an invalid size"); | ||
| 145 | |||
| 146 | struct ReadFactoryCalReply { | ||
| 147 | DataValid status; | ||
| 148 | FactoryCalibration calibration; | ||
| 149 | }; | ||
| 150 | static_assert(sizeof(ReadFactoryCalReply) == 0x14, "ReadFactoryCalReply is an invalid size"); | ||
| 151 | |||
| 152 | struct ReadUserCalReply { | ||
| 153 | DataValid status; | ||
| 154 | UserCalibration calibration; | ||
| 155 | INSERT_PADDING_BYTES(0x4); | ||
| 156 | }; | ||
| 157 | static_assert(sizeof(ReadUserCalReply) == 0x14, "ReadUserCalReply is an invalid size"); | ||
| 158 | |||
| 159 | struct ReadIdReply { | ||
| 160 | DataValid status; | ||
| 161 | u16 id_l_x0; | ||
| 162 | u16 id_l_x0_2; | ||
| 163 | u16 id_l_x4; | ||
| 164 | u16 id_h_x0; | ||
| 165 | u16 id_h_x0_2; | ||
| 166 | u16 id_h_x4; | ||
| 167 | }; | ||
| 168 | static_assert(sizeof(ReadIdReply) == 0x10, "ReadIdReply is an invalid size"); | ||
| 169 | |||
| 170 | struct ErrorReply { | ||
| 171 | DataValid status; | ||
| 172 | INSERT_PADDING_BYTES(0x3); | ||
| 173 | }; | ||
| 174 | static_assert(sizeof(ErrorReply) == 0x8, "ErrorReply is an invalid size"); | ||
| 175 | |||
| 176 | struct RingConData { | ||
| 177 | DataValid status; | ||
| 178 | s16_le data; | ||
| 179 | INSERT_PADDING_BYTES(0x2); | ||
| 180 | }; | ||
| 181 | static_assert(sizeof(RingConData) == 0x8, "RingConData is an invalid size"); | ||
| 182 | |||
| 183 | // Returns RingConData struct with pressure sensor values | ||
| 184 | RingConData GetSensorValue() const; | ||
| 185 | |||
| 186 | // Returns 8 byte reply with firmware version | ||
| 187 | std::vector<u8> GetFirmwareVersionReply() const; | ||
| 188 | |||
| 189 | // Returns 16 byte reply with ID values | ||
| 190 | std::vector<u8> GetReadIdReply() const; | ||
| 191 | |||
| 192 | // (STUBBED) Returns 8 byte reply | ||
| 193 | std::vector<u8> GetC020105Reply() const; | ||
| 194 | |||
| 195 | // (STUBBED) Returns 8 byte empty reply | ||
| 196 | std::vector<u8> GetReadUnkCalReply() const; | ||
| 197 | |||
| 198 | // Returns 20 byte reply with factory calibration values | ||
| 199 | std::vector<u8> GetReadFactoryCalReply() const; | ||
| 200 | |||
| 201 | // Returns 20 byte reply with user calibration values | ||
| 202 | std::vector<u8> GetReadUserCalReply() const; | ||
| 203 | |||
| 204 | // Returns 8 byte reply | ||
| 205 | std::vector<u8> GetReadRepCountReply() const; | ||
| 206 | |||
| 207 | // Returns 8 byte reply | ||
| 208 | std::vector<u8> GetReadTotalPushCountReply() const; | ||
| 209 | |||
| 210 | // Returns 8 byte reply | ||
| 211 | std::vector<u8> GetResetRepCountReply() const; | ||
| 212 | |||
| 213 | // Returns 4 byte save data reply | ||
| 214 | std::vector<u8> GetSaveDataReply() const; | ||
| 215 | |||
| 216 | // Returns 8 byte error reply | ||
| 217 | std::vector<u8> GetErrorReply() const; | ||
| 218 | |||
| 219 | // Returns 8 bit redundancy check from provided data | ||
| 220 | u8 GetCrcValue(const std::vector<u8>& data) const; | ||
| 221 | |||
| 222 | // Converts structs to an u8 vector equivalent | ||
| 223 | template <typename T> | ||
| 224 | std::vector<u8> GetDataVector(const T& reply) const; | ||
| 225 | |||
| 226 | RingConCommands command{RingConCommands::Error}; | ||
| 227 | |||
| 228 | // These counters are used in multitasking mode while the switch is sleeping | ||
| 229 | // Total steps taken | ||
| 230 | u8 total_rep_count = 0; | ||
| 231 | // Total times the ring was pushed | ||
| 232 | u8 total_push_count = 0; | ||
| 233 | |||
| 234 | const u8 device_id = 0x20; | ||
| 235 | const FirmwareVersion version = { | ||
| 236 | .sub = 0x0, | ||
| 237 | .main = 0x2c, | ||
| 238 | }; | ||
| 239 | const FactoryCalibration factory_calibration = { | ||
| 240 | .os_max = idle_value + range + idle_deadzone, | ||
| 241 | .hk_max = idle_value - range - idle_deadzone, | ||
| 242 | .zero_min = idle_value - idle_deadzone, | ||
| 243 | .zero_max = idle_value + idle_deadzone, | ||
| 244 | }; | ||
| 245 | UserCalibration user_calibration = { | ||
| 246 | .os_max = {.value = range, .crc = 228}, | ||
| 247 | .hk_max = {.value = -range, .crc = 239}, | ||
| 248 | .zero = {.value = idle_value, .crc = 225}, | ||
| 249 | }; | ||
| 250 | |||
| 251 | Core::HID::EmulatedController* input; | ||
| 252 | }; | ||
| 253 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/starlink.cpp b/src/core/hle/service/hid/hidbus/starlink.cpp deleted file mode 100644 index 36573274e..000000000 --- a/src/core/hle/service/hid/hidbus/starlink.cpp +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/emulated_controller.h" | ||
| 5 | #include "core/hid/hid_core.h" | ||
| 6 | #include "core/hle/service/hid/hidbus/starlink.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | constexpr u8 DEVICE_ID = 0x28; | ||
| 10 | |||
| 11 | Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_) | ||
| 12 | : HidbusBase(system_, service_context_) {} | ||
| 13 | Starlink::~Starlink() = default; | ||
| 14 | |||
| 15 | void Starlink::OnInit() { | ||
| 16 | return; | ||
| 17 | } | ||
| 18 | |||
| 19 | void Starlink::OnRelease() { | ||
| 20 | return; | ||
| 21 | }; | ||
| 22 | |||
| 23 | void Starlink::OnUpdate() { | ||
| 24 | if (!is_activated) { | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | if (!device_enabled) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | if (!polling_mode_enabled || transfer_memory == 0) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | |||
| 34 | LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); | ||
| 35 | } | ||
| 36 | |||
| 37 | u8 Starlink::GetDeviceId() const { | ||
| 38 | return DEVICE_ID; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::vector<u8> Starlink::GetReply() const { | ||
| 42 | return {}; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool Starlink::SetCommand(std::span<const u8> data) { | ||
| 46 | LOG_ERROR(Service_HID, "Command not implemented"); | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | |||
| 50 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/starlink.h b/src/core/hle/service/hid/hidbus/starlink.h deleted file mode 100644 index a276aa88f..000000000 --- a/src/core/hle/service/hid/hidbus/starlink.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | class EmulatedController; | ||
| 11 | } // namespace Core::HID | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | class Starlink final : public HidbusBase { | ||
| 16 | public: | ||
| 17 | explicit Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 18 | ~Starlink() override; | ||
| 19 | |||
| 20 | void OnInit() override; | ||
| 21 | |||
| 22 | void OnRelease() override; | ||
| 23 | |||
| 24 | // Updates ringcon transfer memory | ||
| 25 | void OnUpdate() override; | ||
| 26 | |||
| 27 | // Returns the device ID of the joycon | ||
| 28 | u8 GetDeviceId() const override; | ||
| 29 | |||
| 30 | // Assigns a command from data | ||
| 31 | bool SetCommand(std::span<const u8> data) override; | ||
| 32 | |||
| 33 | // Returns a reply from a command | ||
| 34 | std::vector<u8> GetReply() const override; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/stubbed.cpp b/src/core/hle/service/hid/hidbus/stubbed.cpp deleted file mode 100644 index 8160b7218..000000000 --- a/src/core/hle/service/hid/hidbus/stubbed.cpp +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/emulated_controller.h" | ||
| 5 | #include "core/hid/hid_core.h" | ||
| 6 | #include "core/hle/service/hid/hidbus/stubbed.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | constexpr u8 DEVICE_ID = 0xFF; | ||
| 10 | |||
| 11 | HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_) | ||
| 12 | : HidbusBase(system_, service_context_) {} | ||
| 13 | HidbusStubbed::~HidbusStubbed() = default; | ||
| 14 | |||
| 15 | void HidbusStubbed::OnInit() { | ||
| 16 | return; | ||
| 17 | } | ||
| 18 | |||
| 19 | void HidbusStubbed::OnRelease() { | ||
| 20 | return; | ||
| 21 | }; | ||
| 22 | |||
| 23 | void HidbusStubbed::OnUpdate() { | ||
| 24 | if (!is_activated) { | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | if (!device_enabled) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | if (!polling_mode_enabled || transfer_memory == 0) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | |||
| 34 | LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); | ||
| 35 | } | ||
| 36 | |||
| 37 | u8 HidbusStubbed::GetDeviceId() const { | ||
| 38 | return DEVICE_ID; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::vector<u8> HidbusStubbed::GetReply() const { | ||
| 42 | return {}; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool HidbusStubbed::SetCommand(std::span<const u8> data) { | ||
| 46 | LOG_ERROR(Service_HID, "Command not implemented"); | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | |||
| 50 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/stubbed.h b/src/core/hle/service/hid/hidbus/stubbed.h deleted file mode 100644 index 2e58d42fc..000000000 --- a/src/core/hle/service/hid/hidbus/stubbed.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | class EmulatedController; | ||
| 11 | } // namespace Core::HID | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | class HidbusStubbed final : public HidbusBase { | ||
| 16 | public: | ||
| 17 | explicit HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 18 | ~HidbusStubbed() override; | ||
| 19 | |||
| 20 | void OnInit() override; | ||
| 21 | |||
| 22 | void OnRelease() override; | ||
| 23 | |||
| 24 | // Updates ringcon transfer memory | ||
| 25 | void OnUpdate() override; | ||
| 26 | |||
| 27 | // Returns the device ID of the joycon | ||
| 28 | u8 GetDeviceId() const override; | ||
| 29 | |||
| 30 | // Assigns a command from data | ||
| 31 | bool SetCommand(std::span<const u8> data) override; | ||
| 32 | |||
| 33 | // Returns a reply from a command | ||
| 34 | std::vector<u8> GetReply() const override; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 05ed31273..18e544f2f 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp | |||
| @@ -6,22 +6,22 @@ | |||
| 6 | 6 | ||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/hid/emulated_controller.h" | ||
| 10 | #include "core/hid/hid_core.h" | ||
| 11 | #include "core/hle/kernel/k_shared_memory.h" | 9 | #include "core/hle/kernel/k_shared_memory.h" |
| 12 | #include "core/hle/kernel/k_transfer_memory.h" | 10 | #include "core/hle/kernel/k_transfer_memory.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/service/hid/errors.h" | ||
| 15 | #include "core/hle/service/hid/hid_util.h" | ||
| 16 | #include "core/hle/service/hid/irs.h" | 12 | #include "core/hle/service/hid/irs.h" |
| 17 | #include "core/hle/service/hid/irsensor/clustering_processor.h" | ||
| 18 | #include "core/hle/service/hid/irsensor/image_transfer_processor.h" | ||
| 19 | #include "core/hle/service/hid/irsensor/ir_led_processor.h" | ||
| 20 | #include "core/hle/service/hid/irsensor/moment_processor.h" | ||
| 21 | #include "core/hle/service/hid/irsensor/pointing_processor.h" | ||
| 22 | #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" | ||
| 23 | #include "core/hle/service/ipc_helpers.h" | 13 | #include "core/hle/service/ipc_helpers.h" |
| 24 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| 15 | #include "hid_core/frontend/emulated_controller.h" | ||
| 16 | #include "hid_core/hid_core.h" | ||
| 17 | #include "hid_core/hid_result.h" | ||
| 18 | #include "hid_core/hid_util.h" | ||
| 19 | #include "hid_core/irsensor/clustering_processor.h" | ||
| 20 | #include "hid_core/irsensor/image_transfer_processor.h" | ||
| 21 | #include "hid_core/irsensor/ir_led_processor.h" | ||
| 22 | #include "hid_core/irsensor/moment_processor.h" | ||
| 23 | #include "hid_core/irsensor/pointing_processor.h" | ||
| 24 | #include "hid_core/irsensor/tera_plugin_processor.h" | ||
| 25 | 25 | ||
| 26 | namespace Service::IRS { | 26 | namespace Service::IRS { |
| 27 | 27 | ||
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index c8e6dab17..06b7279ee 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | #include "hid_core/irsensor/irs_types.h" | ||
| 10 | #include "hid_core/irsensor/processor_base.h" | ||
| 11 | 11 | ||
| 12 | namespace Core::HID { | 12 | namespace Core::HID { |
| 13 | class EmulatedController; | 13 | class EmulatedController; |
diff --git a/src/core/hle/service/hid/irs_ring_lifo.h b/src/core/hle/service/hid/irs_ring_lifo.h deleted file mode 100644 index 255d1d296..000000000 --- a/src/core/hle/service/hid/irs_ring_lifo.h +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | |||
| 12 | template <typename State, std::size_t max_buffer_size> | ||
| 13 | struct Lifo { | ||
| 14 | s64 sampling_number{}; | ||
| 15 | s64 buffer_count{}; | ||
| 16 | std::array<State, max_buffer_size> entries{}; | ||
| 17 | |||
| 18 | const State& ReadCurrentEntry() const { | ||
| 19 | return entries[GetBufferTail()]; | ||
| 20 | } | ||
| 21 | |||
| 22 | const State& ReadPreviousEntry() const { | ||
| 23 | return entries[GetPreviousEntryIndex()]; | ||
| 24 | } | ||
| 25 | |||
| 26 | s64 GetBufferTail() const { | ||
| 27 | return sampling_number % max_buffer_size; | ||
| 28 | } | ||
| 29 | |||
| 30 | std::size_t GetPreviousEntryIndex() const { | ||
| 31 | return static_cast<size_t>((GetBufferTail() + max_buffer_size - 1) % max_buffer_size); | ||
| 32 | } | ||
| 33 | |||
| 34 | std::size_t GetNextEntryIndex() const { | ||
| 35 | return static_cast<size_t>((GetBufferTail() + 1) % max_buffer_size); | ||
| 36 | } | ||
| 37 | |||
| 38 | void WriteNextEntry(const State& new_state) { | ||
| 39 | if (buffer_count < static_cast<s64>(max_buffer_size)) { | ||
| 40 | buffer_count++; | ||
| 41 | } | ||
| 42 | sampling_number++; | ||
| 43 | entries[GetBufferTail()] = new_state; | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp deleted file mode 100644 index c559eb0d5..000000000 --- a/src/core/hle/service/hid/irsensor/clustering_processor.cpp +++ /dev/null | |||
| @@ -1,267 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <queue> | ||
| 5 | |||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/hid/emulated_controller.h" | ||
| 9 | #include "core/hid/hid_core.h" | ||
| 10 | #include "core/hle/service/hid/irsensor/clustering_processor.h" | ||
| 11 | |||
| 12 | namespace Service::IRS { | ||
| 13 | ClusteringProcessor::ClusteringProcessor(Core::System& system_, | ||
| 14 | Core::IrSensor::DeviceFormat& device_format, | ||
| 15 | std::size_t npad_index) | ||
| 16 | : device{device_format}, system{system_} { | ||
| 17 | npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); | ||
| 18 | |||
| 19 | device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; | ||
| 20 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 21 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 22 | SetDefaultConfig(); | ||
| 23 | |||
| 24 | shared_memory = std::construct_at( | ||
| 25 | reinterpret_cast<ClusteringSharedMemory*>(&device_format.state.processor_raw_data)); | ||
| 26 | |||
| 27 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 28 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 29 | .is_npad_service = true, | ||
| 30 | }; | ||
| 31 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 32 | } | ||
| 33 | |||
| 34 | ClusteringProcessor::~ClusteringProcessor() { | ||
| 35 | npad_device->DeleteCallback(callback_key); | ||
| 36 | }; | ||
| 37 | |||
| 38 | void ClusteringProcessor::StartProcessor() { | ||
| 39 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 40 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 41 | } | ||
| 42 | |||
| 43 | void ClusteringProcessor::SuspendProcessor() {} | ||
| 44 | |||
| 45 | void ClusteringProcessor::StopProcessor() {} | ||
| 46 | |||
| 47 | void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 48 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | next_state = {}; | ||
| 53 | const auto& camera_data = npad_device->GetCamera(); | ||
| 54 | auto filtered_image = camera_data.data; | ||
| 55 | |||
| 56 | RemoveLowIntensityData(filtered_image); | ||
| 57 | |||
| 58 | const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); | ||
| 59 | const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); | ||
| 60 | const auto window_end_x = | ||
| 61 | window_start_x + static_cast<std::size_t>(current_config.window_of_interest.width); | ||
| 62 | const auto window_end_y = | ||
| 63 | window_start_y + static_cast<std::size_t>(current_config.window_of_interest.height); | ||
| 64 | |||
| 65 | for (std::size_t y = window_start_y; y < window_end_y; y++) { | ||
| 66 | for (std::size_t x = window_start_x; x < window_end_x; x++) { | ||
| 67 | u8 pixel = GetPixel(filtered_image, x, y); | ||
| 68 | if (pixel == 0) { | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | const auto cluster = GetClusterProperties(filtered_image, x, y); | ||
| 72 | if (cluster.pixel_count > current_config.pixel_count_max) { | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | if (cluster.pixel_count < current_config.pixel_count_min) { | ||
| 76 | continue; | ||
| 77 | } | ||
| 78 | // Cluster object limit reached | ||
| 79 | if (next_state.object_count >= next_state.data.size()) { | ||
| 80 | continue; | ||
| 81 | } | ||
| 82 | next_state.data[next_state.object_count] = cluster; | ||
| 83 | next_state.object_count++; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | next_state.sampling_number = camera_data.sample; | ||
| 88 | next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); | ||
| 89 | next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 90 | shared_memory->clustering_lifo.WriteNextEntry(next_state); | ||
| 91 | |||
| 92 | if (!IsProcessorActive()) { | ||
| 93 | StartProcessor(); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | void ClusteringProcessor::RemoveLowIntensityData(std::vector<u8>& data) { | ||
| 98 | for (u8& pixel : data) { | ||
| 99 | if (pixel < current_config.pixel_count_min) { | ||
| 100 | pixel = 0; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | ClusteringProcessor::ClusteringData ClusteringProcessor::GetClusterProperties(std::vector<u8>& data, | ||
| 106 | std::size_t x, | ||
| 107 | std::size_t y) { | ||
| 108 | using DataPoint = Common::Point<std::size_t>; | ||
| 109 | std::queue<DataPoint> search_points{}; | ||
| 110 | ClusteringData current_cluster = GetPixelProperties(data, x, y); | ||
| 111 | SetPixel(data, x, y, 0); | ||
| 112 | search_points.emplace<DataPoint>({x, y}); | ||
| 113 | |||
| 114 | while (!search_points.empty()) { | ||
| 115 | const auto point = search_points.front(); | ||
| 116 | search_points.pop(); | ||
| 117 | |||
| 118 | // Avoid negative numbers | ||
| 119 | if (point.x == 0 || point.y == 0) { | ||
| 120 | continue; | ||
| 121 | } | ||
| 122 | |||
| 123 | std::array<DataPoint, 4> new_points{ | ||
| 124 | DataPoint{point.x - 1, point.y}, | ||
| 125 | {point.x, point.y - 1}, | ||
| 126 | {point.x + 1, point.y}, | ||
| 127 | {point.x, point.y + 1}, | ||
| 128 | }; | ||
| 129 | |||
| 130 | for (const auto new_point : new_points) { | ||
| 131 | if (new_point.x >= width) { | ||
| 132 | continue; | ||
| 133 | } | ||
| 134 | if (new_point.y >= height) { | ||
| 135 | continue; | ||
| 136 | } | ||
| 137 | if (GetPixel(data, new_point.x, new_point.y) < current_config.object_intensity_min) { | ||
| 138 | continue; | ||
| 139 | } | ||
| 140 | const ClusteringData cluster = GetPixelProperties(data, new_point.x, new_point.y); | ||
| 141 | current_cluster = MergeCluster(current_cluster, cluster); | ||
| 142 | SetPixel(data, new_point.x, new_point.y, 0); | ||
| 143 | search_points.emplace<DataPoint>({new_point.x, new_point.y}); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | return current_cluster; | ||
| 148 | } | ||
| 149 | |||
| 150 | ClusteringProcessor::ClusteringData ClusteringProcessor::GetPixelProperties( | ||
| 151 | const std::vector<u8>& data, std::size_t x, std::size_t y) const { | ||
| 152 | return { | ||
| 153 | .average_intensity = GetPixel(data, x, y) / 255.0f, | ||
| 154 | .centroid = | ||
| 155 | { | ||
| 156 | .x = static_cast<f32>(x), | ||
| 157 | .y = static_cast<f32>(y), | ||
| 158 | |||
| 159 | }, | ||
| 160 | .pixel_count = 1, | ||
| 161 | .bound = | ||
| 162 | { | ||
| 163 | .x = static_cast<s16>(x), | ||
| 164 | .y = static_cast<s16>(y), | ||
| 165 | .width = 1, | ||
| 166 | .height = 1, | ||
| 167 | }, | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster( | ||
| 172 | const ClusteringData a, const ClusteringData b) const { | ||
| 173 | const f32 a_pixel_count = static_cast<f32>(a.pixel_count); | ||
| 174 | const f32 b_pixel_count = static_cast<f32>(b.pixel_count); | ||
| 175 | const f32 pixel_count = a_pixel_count + b_pixel_count; | ||
| 176 | const f32 average_intensity = | ||
| 177 | (a.average_intensity * a_pixel_count + b.average_intensity * b_pixel_count) / pixel_count; | ||
| 178 | const Core::IrSensor::IrsCentroid centroid = { | ||
| 179 | .x = (a.centroid.x * a_pixel_count + b.centroid.x * b_pixel_count) / pixel_count, | ||
| 180 | .y = (a.centroid.y * a_pixel_count + b.centroid.y * b_pixel_count) / pixel_count, | ||
| 181 | }; | ||
| 182 | s16 bound_start_x = a.bound.x < b.bound.x ? a.bound.x : b.bound.x; | ||
| 183 | s16 bound_start_y = a.bound.y < b.bound.y ? a.bound.y : b.bound.y; | ||
| 184 | s16 a_bound_end_x = a.bound.x + a.bound.width; | ||
| 185 | s16 a_bound_end_y = a.bound.y + a.bound.height; | ||
| 186 | s16 b_bound_end_x = b.bound.x + b.bound.width; | ||
| 187 | s16 b_bound_end_y = b.bound.y + b.bound.height; | ||
| 188 | |||
| 189 | const Core::IrSensor::IrsRect bound = { | ||
| 190 | .x = bound_start_x, | ||
| 191 | .y = bound_start_y, | ||
| 192 | .width = a_bound_end_x > b_bound_end_x ? static_cast<s16>(a_bound_end_x - bound_start_x) | ||
| 193 | : static_cast<s16>(b_bound_end_x - bound_start_x), | ||
| 194 | .height = a_bound_end_y > b_bound_end_y ? static_cast<s16>(a_bound_end_y - bound_start_y) | ||
| 195 | : static_cast<s16>(b_bound_end_y - bound_start_y), | ||
| 196 | }; | ||
| 197 | |||
| 198 | return { | ||
| 199 | .average_intensity = average_intensity, | ||
| 200 | .centroid = centroid, | ||
| 201 | .pixel_count = static_cast<u32>(pixel_count), | ||
| 202 | .bound = bound, | ||
| 203 | }; | ||
| 204 | } | ||
| 205 | |||
| 206 | u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { | ||
| 207 | if ((y * width) + x >= data.size()) { | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | return data[(y * width) + x]; | ||
| 211 | } | ||
| 212 | |||
| 213 | void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) { | ||
| 214 | if ((y * width) + x >= data.size()) { | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | data[(y * width) + x] = value; | ||
| 218 | } | ||
| 219 | |||
| 220 | void ClusteringProcessor::SetDefaultConfig() { | ||
| 221 | using namespace std::literals::chrono_literals; | ||
| 222 | current_config.camera_config.exposure_time = std::chrono::microseconds(200ms).count(); | ||
| 223 | current_config.camera_config.gain = 2; | ||
| 224 | current_config.camera_config.is_negative_used = false; | ||
| 225 | current_config.camera_config.light_target = Core::IrSensor::CameraLightTarget::BrightLeds; | ||
| 226 | current_config.window_of_interest = { | ||
| 227 | .x = 0, | ||
| 228 | .y = 0, | ||
| 229 | .width = width, | ||
| 230 | .height = height, | ||
| 231 | }; | ||
| 232 | current_config.pixel_count_min = 3; | ||
| 233 | current_config.pixel_count_max = static_cast<u32>(GetDataSize(format)); | ||
| 234 | current_config.is_external_light_filter_enabled = true; | ||
| 235 | current_config.object_intensity_min = 150; | ||
| 236 | |||
| 237 | npad_device->SetCameraFormat(format); | ||
| 238 | } | ||
| 239 | |||
| 240 | void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) { | ||
| 241 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 242 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 243 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 244 | current_config.camera_config.light_target = | ||
| 245 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 246 | current_config.window_of_interest = config.window_of_interest; | ||
| 247 | current_config.pixel_count_min = config.pixel_count_min; | ||
| 248 | current_config.pixel_count_max = config.pixel_count_max; | ||
| 249 | current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled; | ||
| 250 | current_config.object_intensity_min = config.object_intensity_min; | ||
| 251 | |||
| 252 | LOG_INFO(Service_IRS, | ||
| 253 | "Processor config, exposure_time={}, gain={}, is_negative_used={}, " | ||
| 254 | "light_target={}, window_of_interest=({}, {}, {}, {}), pixel_count_min={}, " | ||
| 255 | "pixel_count_max={}, is_external_light_filter_enabled={}, object_intensity_min={}", | ||
| 256 | current_config.camera_config.exposure_time, current_config.camera_config.gain, | ||
| 257 | current_config.camera_config.is_negative_used, | ||
| 258 | current_config.camera_config.light_target, current_config.window_of_interest.x, | ||
| 259 | current_config.window_of_interest.y, current_config.window_of_interest.width, | ||
| 260 | current_config.window_of_interest.height, current_config.pixel_count_min, | ||
| 261 | current_config.pixel_count_max, current_config.is_external_light_filter_enabled, | ||
| 262 | current_config.object_intensity_min); | ||
| 263 | |||
| 264 | npad_device->SetCameraFormat(format); | ||
| 265 | } | ||
| 266 | |||
| 267 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h deleted file mode 100644 index 83f34734a..000000000 --- a/src/core/hle/service/hid/irsensor/clustering_processor.h +++ /dev/null | |||
| @@ -1,115 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irs_ring_lifo.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Core::HID { | ||
| 16 | class EmulatedController; | ||
| 17 | } // namespace Core::HID | ||
| 18 | |||
| 19 | namespace Service::IRS { | ||
| 20 | class ClusteringProcessor final : public ProcessorBase { | ||
| 21 | public: | ||
| 22 | explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, | ||
| 23 | std::size_t npad_index); | ||
| 24 | ~ClusteringProcessor() override; | ||
| 25 | |||
| 26 | // Called when the processor is initialized | ||
| 27 | void StartProcessor() override; | ||
| 28 | |||
| 29 | // Called when the processor is suspended | ||
| 30 | void SuspendProcessor() override; | ||
| 31 | |||
| 32 | // Called when the processor is stopped | ||
| 33 | void StopProcessor() override; | ||
| 34 | |||
| 35 | // Sets config parameters of the camera | ||
| 36 | void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); | ||
| 37 | |||
| 38 | private: | ||
| 39 | static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size320x240; | ||
| 40 | static constexpr std::size_t width = 320; | ||
| 41 | static constexpr std::size_t height = 240; | ||
| 42 | |||
| 43 | // This is nn::irsensor::ClusteringProcessorConfig | ||
| 44 | struct ClusteringProcessorConfig { | ||
| 45 | Core::IrSensor::CameraConfig camera_config; | ||
| 46 | Core::IrSensor::IrsRect window_of_interest; | ||
| 47 | u32 pixel_count_min; | ||
| 48 | u32 pixel_count_max; | ||
| 49 | u32 object_intensity_min; | ||
| 50 | bool is_external_light_filter_enabled; | ||
| 51 | INSERT_PADDING_BYTES(3); | ||
| 52 | }; | ||
| 53 | static_assert(sizeof(ClusteringProcessorConfig) == 0x30, | ||
| 54 | "ClusteringProcessorConfig is an invalid size"); | ||
| 55 | |||
| 56 | // This is nn::irsensor::AdaptiveClusteringProcessorConfig | ||
| 57 | struct AdaptiveClusteringProcessorConfig { | ||
| 58 | Core::IrSensor::AdaptiveClusteringMode mode; | ||
| 59 | Core::IrSensor::AdaptiveClusteringTargetDistance target_distance; | ||
| 60 | }; | ||
| 61 | static_assert(sizeof(AdaptiveClusteringProcessorConfig) == 0x8, | ||
| 62 | "AdaptiveClusteringProcessorConfig is an invalid size"); | ||
| 63 | |||
| 64 | // This is nn::irsensor::ClusteringData | ||
| 65 | struct ClusteringData { | ||
| 66 | f32 average_intensity; | ||
| 67 | Core::IrSensor::IrsCentroid centroid; | ||
| 68 | u32 pixel_count; | ||
| 69 | Core::IrSensor::IrsRect bound; | ||
| 70 | }; | ||
| 71 | static_assert(sizeof(ClusteringData) == 0x18, "ClusteringData is an invalid size"); | ||
| 72 | |||
| 73 | // This is nn::irsensor::ClusteringProcessorState | ||
| 74 | struct ClusteringProcessorState { | ||
| 75 | s64 sampling_number; | ||
| 76 | u64 timestamp; | ||
| 77 | u8 object_count; | ||
| 78 | INSERT_PADDING_BYTES(3); | ||
| 79 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 80 | std::array<ClusteringData, 0x10> data; | ||
| 81 | }; | ||
| 82 | static_assert(sizeof(ClusteringProcessorState) == 0x198, | ||
| 83 | "ClusteringProcessorState is an invalid size"); | ||
| 84 | |||
| 85 | struct ClusteringSharedMemory { | ||
| 86 | Service::IRS::Lifo<ClusteringProcessorState, 6> clustering_lifo; | ||
| 87 | static_assert(sizeof(clustering_lifo) == 0x9A0, "clustering_lifo is an invalid size"); | ||
| 88 | INSERT_PADDING_WORDS(0x11F); | ||
| 89 | }; | ||
| 90 | static_assert(sizeof(ClusteringSharedMemory) == 0xE20, | ||
| 91 | "ClusteringSharedMemory is an invalid size"); | ||
| 92 | |||
| 93 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 94 | void RemoveLowIntensityData(std::vector<u8>& data); | ||
| 95 | ClusteringData GetClusterProperties(std::vector<u8>& data, std::size_t x, std::size_t y); | ||
| 96 | ClusteringData GetPixelProperties(const std::vector<u8>& data, std::size_t x, | ||
| 97 | std::size_t y) const; | ||
| 98 | ClusteringData MergeCluster(const ClusteringData a, const ClusteringData b) const; | ||
| 99 | u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; | ||
| 100 | void SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value); | ||
| 101 | |||
| 102 | // Sets config parameters of the camera | ||
| 103 | void SetDefaultConfig(); | ||
| 104 | |||
| 105 | ClusteringSharedMemory* shared_memory = nullptr; | ||
| 106 | ClusteringProcessorState next_state{}; | ||
| 107 | |||
| 108 | ClusteringProcessorConfig current_config{}; | ||
| 109 | Core::IrSensor::DeviceFormat& device; | ||
| 110 | Core::HID::EmulatedController* npad_device; | ||
| 111 | int callback_key{}; | ||
| 112 | |||
| 113 | Core::System& system; | ||
| 114 | }; | ||
| 115 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp deleted file mode 100644 index 22067a591..000000000 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp +++ /dev/null | |||
| @@ -1,155 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hid/emulated_controller.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hle/service/hid/irsensor/image_transfer_processor.h" | ||
| 8 | #include "core/memory.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | ImageTransferProcessor::ImageTransferProcessor(Core::System& system_, | ||
| 12 | Core::IrSensor::DeviceFormat& device_format, | ||
| 13 | std::size_t npad_index) | ||
| 14 | : device{device_format}, system{system_} { | ||
| 15 | npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); | ||
| 16 | |||
| 17 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 18 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 19 | .is_npad_service = true, | ||
| 20 | }; | ||
| 21 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 22 | |||
| 23 | device.mode = Core::IrSensor::IrSensorMode::ImageTransferProcessor; | ||
| 24 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 25 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 26 | } | ||
| 27 | |||
| 28 | ImageTransferProcessor::~ImageTransferProcessor() { | ||
| 29 | npad_device->DeleteCallback(callback_key); | ||
| 30 | }; | ||
| 31 | |||
| 32 | void ImageTransferProcessor::StartProcessor() { | ||
| 33 | is_active = true; | ||
| 34 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 35 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 36 | processor_state.sampling_number = 0; | ||
| 37 | processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 38 | } | ||
| 39 | |||
| 40 | void ImageTransferProcessor::SuspendProcessor() {} | ||
| 41 | |||
| 42 | void ImageTransferProcessor::StopProcessor() {} | ||
| 43 | |||
| 44 | void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 45 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | if (transfer_memory == 0) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | const auto& camera_data = npad_device->GetCamera(); | ||
| 53 | |||
| 54 | // This indicates how much ambient light is present | ||
| 55 | processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 56 | processor_state.sampling_number = camera_data.sample; | ||
| 57 | |||
| 58 | if (camera_data.format != current_config.origin_format) { | ||
| 59 | LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, | ||
| 60 | current_config.origin_format); | ||
| 61 | system.ApplicationMemory().ZeroBlock(transfer_memory, | ||
| 62 | GetDataSize(current_config.trimming_format)); | ||
| 63 | return; | ||
| 64 | } | ||
| 65 | |||
| 66 | if (current_config.origin_format > current_config.trimming_format) { | ||
| 67 | LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", | ||
| 68 | current_config.origin_format, current_config.trimming_format); | ||
| 69 | system.ApplicationMemory().ZeroBlock(transfer_memory, | ||
| 70 | GetDataSize(current_config.trimming_format)); | ||
| 71 | return; | ||
| 72 | } | ||
| 73 | |||
| 74 | std::vector<u8> window_data{}; | ||
| 75 | const auto origin_width = GetDataWidth(current_config.origin_format); | ||
| 76 | const auto origin_height = GetDataHeight(current_config.origin_format); | ||
| 77 | const auto trimming_width = GetDataWidth(current_config.trimming_format); | ||
| 78 | const auto trimming_height = GetDataHeight(current_config.trimming_format); | ||
| 79 | window_data.resize(GetDataSize(current_config.trimming_format)); | ||
| 80 | |||
| 81 | if (trimming_width + current_config.trimming_start_x > origin_width || | ||
| 82 | trimming_height + current_config.trimming_start_y > origin_height) { | ||
| 83 | LOG_WARNING(Service_IRS, | ||
| 84 | "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", | ||
| 85 | current_config.trimming_start_x, current_config.trimming_start_y, | ||
| 86 | trimming_width, trimming_height, origin_width, origin_height); | ||
| 87 | system.ApplicationMemory().ZeroBlock(transfer_memory, | ||
| 88 | GetDataSize(current_config.trimming_format)); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | for (std::size_t y = 0; y < trimming_height; y++) { | ||
| 93 | for (std::size_t x = 0; x < trimming_width; x++) { | ||
| 94 | const std::size_t window_index = (y * trimming_width) + x; | ||
| 95 | const std::size_t origin_index = | ||
| 96 | ((y + current_config.trimming_start_y) * origin_width) + x + | ||
| 97 | current_config.trimming_start_x; | ||
| 98 | window_data[window_index] = camera_data.data[origin_index]; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(), | ||
| 103 | GetDataSize(current_config.trimming_format)); | ||
| 104 | |||
| 105 | if (!IsProcessorActive()) { | ||
| 106 | StartProcessor(); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | void ImageTransferProcessor::SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config) { | ||
| 111 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 112 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 113 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 114 | current_config.camera_config.light_target = | ||
| 115 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 116 | current_config.origin_format = | ||
| 117 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); | ||
| 118 | current_config.trimming_format = | ||
| 119 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); | ||
| 120 | current_config.trimming_start_x = 0; | ||
| 121 | current_config.trimming_start_y = 0; | ||
| 122 | |||
| 123 | npad_device->SetCameraFormat(current_config.origin_format); | ||
| 124 | } | ||
| 125 | |||
| 126 | void ImageTransferProcessor::SetConfig( | ||
| 127 | Core::IrSensor::PackedImageTransferProcessorExConfig config) { | ||
| 128 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 129 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 130 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 131 | current_config.camera_config.light_target = | ||
| 132 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 133 | current_config.origin_format = | ||
| 134 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.origin_format); | ||
| 135 | current_config.trimming_format = | ||
| 136 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.trimming_format); | ||
| 137 | current_config.trimming_start_x = config.trimming_start_x; | ||
| 138 | current_config.trimming_start_y = config.trimming_start_y; | ||
| 139 | |||
| 140 | npad_device->SetCameraFormat(current_config.origin_format); | ||
| 141 | } | ||
| 142 | |||
| 143 | void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { | ||
| 144 | transfer_memory = t_mem; | ||
| 145 | } | ||
| 146 | |||
| 147 | Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( | ||
| 148 | std::vector<u8>& data) const { | ||
| 149 | const auto size = GetDataSize(current_config.trimming_format); | ||
| 150 | data.resize(size); | ||
| 151 | system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); | ||
| 152 | return processor_state; | ||
| 153 | } | ||
| 154 | |||
| 155 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.h b/src/core/hle/service/hid/irsensor/image_transfer_processor.h deleted file mode 100644 index 7f42d8453..000000000 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.h +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/typed_address.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 9 | |||
| 10 | namespace Core { | ||
| 11 | class System; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Core::HID { | ||
| 15 | class EmulatedController; | ||
| 16 | } // namespace Core::HID | ||
| 17 | |||
| 18 | namespace Service::IRS { | ||
| 19 | class ImageTransferProcessor final : public ProcessorBase { | ||
| 20 | public: | ||
| 21 | explicit ImageTransferProcessor(Core::System& system_, | ||
| 22 | Core::IrSensor::DeviceFormat& device_format, | ||
| 23 | std::size_t npad_index); | ||
| 24 | ~ImageTransferProcessor() override; | ||
| 25 | |||
| 26 | // Called when the processor is initialized | ||
| 27 | void StartProcessor() override; | ||
| 28 | |||
| 29 | // Called when the processor is suspended | ||
| 30 | void SuspendProcessor() override; | ||
| 31 | |||
| 32 | // Called when the processor is stopped | ||
| 33 | void StopProcessor() override; | ||
| 34 | |||
| 35 | // Sets config parameters of the camera | ||
| 36 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config); | ||
| 37 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); | ||
| 38 | |||
| 39 | // Transfer memory where the image data will be stored | ||
| 40 | void SetTransferMemoryAddress(Common::ProcessAddress t_mem); | ||
| 41 | |||
| 42 | Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; | ||
| 43 | |||
| 44 | private: | ||
| 45 | // This is nn::irsensor::ImageTransferProcessorConfig | ||
| 46 | struct ImageTransferProcessorConfig { | ||
| 47 | Core::IrSensor::CameraConfig camera_config; | ||
| 48 | Core::IrSensor::ImageTransferProcessorFormat format; | ||
| 49 | }; | ||
| 50 | static_assert(sizeof(ImageTransferProcessorConfig) == 0x20, | ||
| 51 | "ImageTransferProcessorConfig is an invalid size"); | ||
| 52 | |||
| 53 | // This is nn::irsensor::ImageTransferProcessorExConfig | ||
| 54 | struct ImageTransferProcessorExConfig { | ||
| 55 | Core::IrSensor::CameraConfig camera_config; | ||
| 56 | Core::IrSensor::ImageTransferProcessorFormat origin_format; | ||
| 57 | Core::IrSensor::ImageTransferProcessorFormat trimming_format; | ||
| 58 | u16 trimming_start_x; | ||
| 59 | u16 trimming_start_y; | ||
| 60 | bool is_external_light_filter_enabled; | ||
| 61 | INSERT_PADDING_BYTES(3); | ||
| 62 | }; | ||
| 63 | static_assert(sizeof(ImageTransferProcessorExConfig) == 0x28, | ||
| 64 | "ImageTransferProcessorExConfig is an invalid size"); | ||
| 65 | |||
| 66 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 67 | |||
| 68 | ImageTransferProcessorExConfig current_config{}; | ||
| 69 | Core::IrSensor::ImageTransferProcessorState processor_state{}; | ||
| 70 | Core::IrSensor::DeviceFormat& device; | ||
| 71 | Core::HID::EmulatedController* npad_device; | ||
| 72 | int callback_key{}; | ||
| 73 | |||
| 74 | Core::System& system; | ||
| 75 | Common::ProcessAddress transfer_memory{}; | ||
| 76 | }; | ||
| 77 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/ir_led_processor.cpp b/src/core/hle/service/hid/irsensor/ir_led_processor.cpp deleted file mode 100644 index 8e6dd99e4..000000000 --- a/src/core/hle/service/hid/irsensor/ir_led_processor.cpp +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/ir_led_processor.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | IrLedProcessor::IrLedProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::IrLedProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | IrLedProcessor::~IrLedProcessor() = default; | ||
| 15 | |||
| 16 | void IrLedProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void IrLedProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void IrLedProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void IrLedProcessor::SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config) { | ||
| 23 | current_config.light_target = | ||
| 24 | static_cast<Core::IrSensor::CameraLightTarget>(config.light_target); | ||
| 25 | } | ||
| 26 | |||
| 27 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/ir_led_processor.h b/src/core/hle/service/hid/irsensor/ir_led_processor.h deleted file mode 100644 index c3d8693c9..000000000 --- a/src/core/hle/service/hid/irsensor/ir_led_processor.h +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class IrLedProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit IrLedProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~IrLedProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::IrLedProcessorConfig | ||
| 31 | struct IrLedProcessorConfig { | ||
| 32 | Core::IrSensor::CameraLightTarget light_target; | ||
| 33 | }; | ||
| 34 | static_assert(sizeof(IrLedProcessorConfig) == 0x4, "IrLedProcessorConfig is an invalid size"); | ||
| 35 | |||
| 36 | struct IrLedProcessorState { | ||
| 37 | s64 sampling_number; | ||
| 38 | u64 timestamp; | ||
| 39 | std::array<u8, 0x8> data; | ||
| 40 | }; | ||
| 41 | static_assert(sizeof(IrLedProcessorState) == 0x18, "IrLedProcessorState is an invalid size"); | ||
| 42 | |||
| 43 | IrLedProcessorConfig current_config{}; | ||
| 44 | Core::IrSensor::DeviceFormat& device; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.cpp b/src/core/hle/service/hid/irsensor/moment_processor.cpp deleted file mode 100644 index cf045bda7..000000000 --- a/src/core/hle/service/hid/irsensor/moment_processor.cpp +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/moment_processor.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30; | ||
| 12 | static constexpr std::size_t ImageWidth = 40; | ||
| 13 | static constexpr std::size_t ImageHeight = 30; | ||
| 14 | |||
| 15 | MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, | ||
| 16 | std::size_t npad_index) | ||
| 17 | : device(device_format), system{system_} { | ||
| 18 | npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); | ||
| 19 | |||
| 20 | device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; | ||
| 21 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 22 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 23 | |||
| 24 | shared_memory = std::construct_at( | ||
| 25 | reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data)); | ||
| 26 | |||
| 27 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 28 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 29 | .is_npad_service = true, | ||
| 30 | }; | ||
| 31 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 32 | } | ||
| 33 | |||
| 34 | MomentProcessor::~MomentProcessor() { | ||
| 35 | npad_device->DeleteCallback(callback_key); | ||
| 36 | }; | ||
| 37 | |||
| 38 | void MomentProcessor::StartProcessor() { | ||
| 39 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 40 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 41 | } | ||
| 42 | |||
| 43 | void MomentProcessor::SuspendProcessor() {} | ||
| 44 | |||
| 45 | void MomentProcessor::StopProcessor() {} | ||
| 46 | |||
| 47 | void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 48 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | next_state = {}; | ||
| 53 | const auto& camera_data = npad_device->GetCamera(); | ||
| 54 | |||
| 55 | const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width); | ||
| 56 | const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height); | ||
| 57 | const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); | ||
| 58 | const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); | ||
| 59 | |||
| 60 | const std::size_t block_width = window_width / Columns; | ||
| 61 | const std::size_t block_height = window_height / Rows; | ||
| 62 | |||
| 63 | for (std::size_t row = 0; row < Rows; row++) { | ||
| 64 | for (std::size_t column = 0; column < Columns; column++) { | ||
| 65 | const size_t x_pos = (column * block_width) + window_start_x; | ||
| 66 | const size_t y_pos = (row * block_height) + window_start_y; | ||
| 67 | auto& statistic = next_state.statistic[column + (row * Columns)]; | ||
| 68 | statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | next_state.sampling_number = camera_data.sample; | ||
| 73 | next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); | ||
| 74 | next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 75 | shared_memory->moment_lifo.WriteNextEntry(next_state); | ||
| 76 | |||
| 77 | if (!IsProcessorActive()) { | ||
| 78 | StartProcessor(); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { | ||
| 83 | if ((y * ImageWidth) + x >= data.size()) { | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | return data[(y * ImageWidth) + x]; | ||
| 87 | } | ||
| 88 | |||
| 89 | MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data, | ||
| 90 | std::size_t start_x, | ||
| 91 | std::size_t start_y, | ||
| 92 | std::size_t width, | ||
| 93 | std::size_t height) const { | ||
| 94 | // The actual implementation is always 320x240 | ||
| 95 | static constexpr std::size_t RealWidth = 320; | ||
| 96 | static constexpr std::size_t RealHeight = 240; | ||
| 97 | static constexpr std::size_t Threshold = 30; | ||
| 98 | MomentStatistic statistic{}; | ||
| 99 | std::size_t active_points{}; | ||
| 100 | |||
| 101 | // Sum all data points on the block that meet with the threshold | ||
| 102 | for (std::size_t y = 0; y < width; y++) { | ||
| 103 | for (std::size_t x = 0; x < height; x++) { | ||
| 104 | const size_t x_pos = x + start_x; | ||
| 105 | const size_t y_pos = y + start_y; | ||
| 106 | const auto pixel = | ||
| 107 | GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight); | ||
| 108 | |||
| 109 | if (pixel < Threshold) { | ||
| 110 | continue; | ||
| 111 | } | ||
| 112 | |||
| 113 | statistic.average_intensity += pixel; | ||
| 114 | |||
| 115 | statistic.centroid.x += static_cast<float>(x_pos); | ||
| 116 | statistic.centroid.y += static_cast<float>(y_pos); | ||
| 117 | |||
| 118 | active_points++; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | // Return an empty field if no points were available | ||
| 123 | if (active_points == 0) { | ||
| 124 | return {}; | ||
| 125 | } | ||
| 126 | |||
| 127 | // Finally calculate the actual centroid and average intensity | ||
| 128 | statistic.centroid.x /= static_cast<float>(active_points); | ||
| 129 | statistic.centroid.y /= static_cast<float>(active_points); | ||
| 130 | statistic.average_intensity /= static_cast<f32>(width * height); | ||
| 131 | |||
| 132 | return statistic; | ||
| 133 | } | ||
| 134 | |||
| 135 | void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { | ||
| 136 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 137 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 138 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 139 | current_config.camera_config.light_target = | ||
| 140 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 141 | current_config.window_of_interest = config.window_of_interest; | ||
| 142 | current_config.preprocess = | ||
| 143 | static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); | ||
| 144 | current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; | ||
| 145 | |||
| 146 | npad_device->SetCameraFormat(format); | ||
| 147 | } | ||
| 148 | |||
| 149 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.h b/src/core/hle/service/hid/irsensor/moment_processor.h deleted file mode 100644 index 398cfbdc1..000000000 --- a/src/core/hle/service/hid/irsensor/moment_processor.h +++ /dev/null | |||
| @@ -1,91 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irs_ring_lifo.h" | ||
| 10 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Core::HID { | ||
| 17 | class EmulatedController; | ||
| 18 | } // namespace Core::HID | ||
| 19 | |||
| 20 | namespace Service::IRS { | ||
| 21 | class MomentProcessor final : public ProcessorBase { | ||
| 22 | public: | ||
| 23 | explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, | ||
| 24 | std::size_t npad_index); | ||
| 25 | ~MomentProcessor() override; | ||
| 26 | |||
| 27 | // Called when the processor is initialized | ||
| 28 | void StartProcessor() override; | ||
| 29 | |||
| 30 | // Called when the processor is suspended | ||
| 31 | void SuspendProcessor() override; | ||
| 32 | |||
| 33 | // Called when the processor is stopped | ||
| 34 | void StopProcessor() override; | ||
| 35 | |||
| 36 | // Sets config parameters of the camera | ||
| 37 | void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); | ||
| 38 | |||
| 39 | private: | ||
| 40 | static constexpr std::size_t Columns = 8; | ||
| 41 | static constexpr std::size_t Rows = 6; | ||
| 42 | |||
| 43 | // This is nn::irsensor::MomentProcessorConfig | ||
| 44 | struct MomentProcessorConfig { | ||
| 45 | Core::IrSensor::CameraConfig camera_config; | ||
| 46 | Core::IrSensor::IrsRect window_of_interest; | ||
| 47 | Core::IrSensor::MomentProcessorPreprocess preprocess; | ||
| 48 | u32 preprocess_intensity_threshold; | ||
| 49 | }; | ||
| 50 | static_assert(sizeof(MomentProcessorConfig) == 0x28, | ||
| 51 | "MomentProcessorConfig is an invalid size"); | ||
| 52 | |||
| 53 | // This is nn::irsensor::MomentStatistic | ||
| 54 | struct MomentStatistic { | ||
| 55 | f32 average_intensity; | ||
| 56 | Core::IrSensor::IrsCentroid centroid; | ||
| 57 | }; | ||
| 58 | static_assert(sizeof(MomentStatistic) == 0xC, "MomentStatistic is an invalid size"); | ||
| 59 | |||
| 60 | // This is nn::irsensor::MomentProcessorState | ||
| 61 | struct MomentProcessorState { | ||
| 62 | s64 sampling_number; | ||
| 63 | u64 timestamp; | ||
| 64 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 65 | INSERT_PADDING_BYTES(4); | ||
| 66 | std::array<MomentStatistic, Columns * Rows> statistic; | ||
| 67 | }; | ||
| 68 | static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); | ||
| 69 | |||
| 70 | struct MomentSharedMemory { | ||
| 71 | Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo; | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size"); | ||
| 74 | |||
| 75 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 76 | u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; | ||
| 77 | MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x, | ||
| 78 | std::size_t start_y, std::size_t width, std::size_t height) const; | ||
| 79 | |||
| 80 | MomentSharedMemory* shared_memory = nullptr; | ||
| 81 | MomentProcessorState next_state{}; | ||
| 82 | |||
| 83 | MomentProcessorConfig current_config{}; | ||
| 84 | Core::IrSensor::DeviceFormat& device; | ||
| 85 | Core::HID::EmulatedController* npad_device; | ||
| 86 | int callback_key{}; | ||
| 87 | |||
| 88 | Core::System& system; | ||
| 89 | }; | ||
| 90 | |||
| 91 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.cpp b/src/core/hle/service/hid/irsensor/pointing_processor.cpp deleted file mode 100644 index 929f177fc..000000000 --- a/src/core/hle/service/hid/irsensor/pointing_processor.cpp +++ /dev/null | |||
| @@ -1,26 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/pointing_processor.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | PointingProcessor::PointingProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::PointingProcessorMarker; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | PointingProcessor::~PointingProcessor() = default; | ||
| 15 | |||
| 16 | void PointingProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void PointingProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void PointingProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void PointingProcessor::SetConfig(Core::IrSensor::PackedPointingProcessorConfig config) { | ||
| 23 | current_config.window_of_interest = config.window_of_interest; | ||
| 24 | } | ||
| 25 | |||
| 26 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.h b/src/core/hle/service/hid/irsensor/pointing_processor.h deleted file mode 100644 index d63423aff..000000000 --- a/src/core/hle/service/hid/irsensor/pointing_processor.h +++ /dev/null | |||
| @@ -1,61 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | class PointingProcessor final : public ProcessorBase { | ||
| 12 | public: | ||
| 13 | explicit PointingProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 14 | ~PointingProcessor() override; | ||
| 15 | |||
| 16 | // Called when the processor is initialized | ||
| 17 | void StartProcessor() override; | ||
| 18 | |||
| 19 | // Called when the processor is suspended | ||
| 20 | void SuspendProcessor() override; | ||
| 21 | |||
| 22 | // Called when the processor is stopped | ||
| 23 | void StopProcessor() override; | ||
| 24 | |||
| 25 | // Sets config parameters of the camera | ||
| 26 | void SetConfig(Core::IrSensor::PackedPointingProcessorConfig config); | ||
| 27 | |||
| 28 | private: | ||
| 29 | // This is nn::irsensor::PointingProcessorConfig | ||
| 30 | struct PointingProcessorConfig { | ||
| 31 | Core::IrSensor::IrsRect window_of_interest; | ||
| 32 | }; | ||
| 33 | static_assert(sizeof(PointingProcessorConfig) == 0x8, | ||
| 34 | "PointingProcessorConfig is an invalid size"); | ||
| 35 | |||
| 36 | struct PointingProcessorMarkerData { | ||
| 37 | u8 pointing_status; | ||
| 38 | INSERT_PADDING_BYTES(3); | ||
| 39 | u32 unknown; | ||
| 40 | float unknown_float1; | ||
| 41 | float position_x; | ||
| 42 | float position_y; | ||
| 43 | float unknown_float2; | ||
| 44 | Core::IrSensor::IrsRect window_of_interest; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(PointingProcessorMarkerData) == 0x20, | ||
| 47 | "PointingProcessorMarkerData is an invalid size"); | ||
| 48 | |||
| 49 | struct PointingProcessorMarkerState { | ||
| 50 | s64 sampling_number; | ||
| 51 | u64 timestamp; | ||
| 52 | std::array<PointingProcessorMarkerData, 0x3> data; | ||
| 53 | }; | ||
| 54 | static_assert(sizeof(PointingProcessorMarkerState) == 0x70, | ||
| 55 | "PointingProcessorMarkerState is an invalid size"); | ||
| 56 | |||
| 57 | PointingProcessorConfig current_config{}; | ||
| 58 | Core::IrSensor::DeviceFormat& device; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/processor_base.cpp b/src/core/hle/service/hid/irsensor/processor_base.cpp deleted file mode 100644 index 4d43ca17a..000000000 --- a/src/core/hle/service/hid/irsensor/processor_base.cpp +++ /dev/null | |||
| @@ -1,67 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | |||
| 8 | ProcessorBase::ProcessorBase() {} | ||
| 9 | ProcessorBase::~ProcessorBase() = default; | ||
| 10 | |||
| 11 | bool ProcessorBase::IsProcessorActive() const { | ||
| 12 | return is_active; | ||
| 13 | } | ||
| 14 | |||
| 15 | std::size_t ProcessorBase::GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 16 | switch (format) { | ||
| 17 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 18 | return 320 * 240; | ||
| 19 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 20 | return 160 * 120; | ||
| 21 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 22 | return 80 * 60; | ||
| 23 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 24 | return 40 * 30; | ||
| 25 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 26 | return 20 * 15; | ||
| 27 | default: | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | std::size_t ProcessorBase::GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 33 | switch (format) { | ||
| 34 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 35 | return 320; | ||
| 36 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 37 | return 160; | ||
| 38 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 39 | return 80; | ||
| 40 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 41 | return 40; | ||
| 42 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 43 | return 20; | ||
| 44 | default: | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | std::size_t ProcessorBase::GetDataHeight( | ||
| 50 | Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 51 | switch (format) { | ||
| 52 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 53 | return 240; | ||
| 54 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 55 | return 120; | ||
| 56 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 57 | return 60; | ||
| 58 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 59 | return 30; | ||
| 60 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 61 | return 15; | ||
| 62 | default: | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/processor_base.h b/src/core/hle/service/hid/irsensor/processor_base.h deleted file mode 100644 index bc0d2977b..000000000 --- a/src/core/hle/service/hid/irsensor/processor_base.h +++ /dev/null | |||
| @@ -1,33 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | |||
| 9 | namespace Service::IRS { | ||
| 10 | class ProcessorBase { | ||
| 11 | public: | ||
| 12 | explicit ProcessorBase(); | ||
| 13 | virtual ~ProcessorBase(); | ||
| 14 | |||
| 15 | virtual void StartProcessor() = 0; | ||
| 16 | virtual void SuspendProcessor() = 0; | ||
| 17 | virtual void StopProcessor() = 0; | ||
| 18 | |||
| 19 | bool IsProcessorActive() const; | ||
| 20 | |||
| 21 | protected: | ||
| 22 | /// Returns the number of bytes the image uses | ||
| 23 | std::size_t GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 24 | |||
| 25 | /// Returns the width of the image | ||
| 26 | std::size_t GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 27 | |||
| 28 | /// Returns the height of the image | ||
| 29 | std::size_t GetDataHeight(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 30 | |||
| 31 | bool is_active{false}; | ||
| 32 | }; | ||
| 33 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp b/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp deleted file mode 100644 index e691c840a..000000000 --- a/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp +++ /dev/null | |||
| @@ -1,29 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | TeraPluginProcessor::TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::TeraPluginProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | TeraPluginProcessor::~TeraPluginProcessor() = default; | ||
| 15 | |||
| 16 | void TeraPluginProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void TeraPluginProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void TeraPluginProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void TeraPluginProcessor::SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config) { | ||
| 23 | current_config.mode = config.mode; | ||
| 24 | current_config.unknown_1 = config.unknown_1; | ||
| 25 | current_config.unknown_2 = config.unknown_2; | ||
| 26 | current_config.unknown_3 = config.unknown_3; | ||
| 27 | } | ||
| 28 | |||
| 29 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/tera_plugin_processor.h b/src/core/hle/service/hid/irsensor/tera_plugin_processor.h deleted file mode 100644 index bbea7ed0b..000000000 --- a/src/core/hle/service/hid/irsensor/tera_plugin_processor.h +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class TeraPluginProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~TeraPluginProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::TeraPluginProcessorConfig | ||
| 31 | struct TeraPluginProcessorConfig { | ||
| 32 | u8 mode; | ||
| 33 | u8 unknown_1; | ||
| 34 | u8 unknown_2; | ||
| 35 | u8 unknown_3; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(TeraPluginProcessorConfig) == 0x4, | ||
| 38 | "TeraPluginProcessorConfig is an invalid size"); | ||
| 39 | |||
| 40 | struct TeraPluginProcessorState { | ||
| 41 | s64 sampling_number; | ||
| 42 | u64 timestamp; | ||
| 43 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 44 | std::array<u8, 0x12c> data; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(TeraPluginProcessorState) == 0x140, | ||
| 47 | "TeraPluginProcessorState is an invalid size"); | ||
| 48 | |||
| 49 | TeraPluginProcessorConfig current_config{}; | ||
| 50 | Core::IrSensor::DeviceFormat& device; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp deleted file mode 100644 index 1f41e645d..000000000 --- a/src/core/hle/service/hid/resource_manager.cpp +++ /dev/null | |||
| @@ -1,362 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/core_timing.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 9 | #include "core/hle/service/hid/resource_manager.h" | ||
| 10 | #include "core/hle/service/ipc_helpers.h" | ||
| 11 | |||
| 12 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 13 | #include "core/hle/service/hid/controllers/capture_button.h" | ||
| 14 | #include "core/hle/service/hid/controllers/console_six_axis.h" | ||
| 15 | #include "core/hle/service/hid/controllers/debug_mouse.h" | ||
| 16 | #include "core/hle/service/hid/controllers/debug_pad.h" | ||
| 17 | #include "core/hle/service/hid/controllers/digitizer.h" | ||
| 18 | #include "core/hle/service/hid/controllers/gesture.h" | ||
| 19 | #include "core/hle/service/hid/controllers/home_button.h" | ||
| 20 | #include "core/hle/service/hid/controllers/keyboard.h" | ||
| 21 | #include "core/hle/service/hid/controllers/mouse.h" | ||
| 22 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 23 | #include "core/hle/service/hid/controllers/palma.h" | ||
| 24 | #include "core/hle/service/hid/controllers/seven_six_axis.h" | ||
| 25 | #include "core/hle/service/hid/controllers/six_axis.h" | ||
| 26 | #include "core/hle/service/hid/controllers/sleep_button.h" | ||
| 27 | #include "core/hle/service/hid/controllers/touchscreen.h" | ||
| 28 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 29 | #include "core/hle/service/hid/controllers/unique_pad.h" | ||
| 30 | |||
| 31 | namespace Service::HID { | ||
| 32 | |||
| 33 | // Updating period for each HID device. | ||
| 34 | // Period time is obtained by measuring the number of samples in a second on HW using a homebrew | ||
| 35 | // Correct npad_update_ns is 4ms this is overclocked to lower input lag | ||
| 36 | constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) | ||
| 37 | constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) | ||
| 38 | constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) | ||
| 39 | constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) | ||
| 40 | |||
| 41 | ResourceManager::ResourceManager(Core::System& system_) | ||
| 42 | : system{system_}, service_context{system_, "hid"} { | ||
| 43 | applet_resource = std::make_shared<AppletResource>(system); | ||
| 44 | } | ||
| 45 | |||
| 46 | ResourceManager::~ResourceManager() = default; | ||
| 47 | |||
| 48 | void ResourceManager::Initialize() { | ||
| 49 | if (is_initialized) { | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | |||
| 53 | system.HIDCore().ReloadInputDevices(); | ||
| 54 | |||
| 55 | InitializeHidCommonSampler(); | ||
| 56 | InitializeTouchScreenSampler(); | ||
| 57 | InitializeConsoleSixAxisSampler(); | ||
| 58 | InitializeAHidSampler(); | ||
| 59 | |||
| 60 | is_initialized = true; | ||
| 61 | } | ||
| 62 | |||
| 63 | std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const { | ||
| 64 | return applet_resource; | ||
| 65 | } | ||
| 66 | |||
| 67 | std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const { | ||
| 68 | return capture_button; | ||
| 69 | } | ||
| 70 | |||
| 71 | std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const { | ||
| 72 | return console_six_axis; | ||
| 73 | } | ||
| 74 | |||
| 75 | std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const { | ||
| 76 | return debug_mouse; | ||
| 77 | } | ||
| 78 | |||
| 79 | std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const { | ||
| 80 | return debug_pad; | ||
| 81 | } | ||
| 82 | |||
| 83 | std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const { | ||
| 84 | return digitizer; | ||
| 85 | } | ||
| 86 | |||
| 87 | std::shared_ptr<Gesture> ResourceManager::GetGesture() const { | ||
| 88 | return gesture; | ||
| 89 | } | ||
| 90 | |||
| 91 | std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const { | ||
| 92 | return home_button; | ||
| 93 | } | ||
| 94 | |||
| 95 | std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const { | ||
| 96 | return keyboard; | ||
| 97 | } | ||
| 98 | |||
| 99 | std::shared_ptr<Mouse> ResourceManager::GetMouse() const { | ||
| 100 | return mouse; | ||
| 101 | } | ||
| 102 | |||
| 103 | std::shared_ptr<NPad> ResourceManager::GetNpad() const { | ||
| 104 | return npad; | ||
| 105 | } | ||
| 106 | |||
| 107 | std::shared_ptr<Palma> ResourceManager::GetPalma() const { | ||
| 108 | return palma; | ||
| 109 | } | ||
| 110 | |||
| 111 | std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const { | ||
| 112 | return seven_six_axis; | ||
| 113 | } | ||
| 114 | |||
| 115 | std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const { | ||
| 116 | return six_axis; | ||
| 117 | } | ||
| 118 | |||
| 119 | std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const { | ||
| 120 | return sleep_button; | ||
| 121 | } | ||
| 122 | |||
| 123 | std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const { | ||
| 124 | return touch_screen; | ||
| 125 | } | ||
| 126 | |||
| 127 | std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const { | ||
| 128 | return unique_pad; | ||
| 129 | } | ||
| 130 | |||
| 131 | Result ResourceManager::CreateAppletResource(u64 aruid) { | ||
| 132 | if (aruid == SystemAruid) { | ||
| 133 | const auto result = RegisterCoreAppletResource(); | ||
| 134 | if (result.IsError()) { | ||
| 135 | return result; | ||
| 136 | } | ||
| 137 | return GetNpad()->ActivateNpadResource(); | ||
| 138 | } | ||
| 139 | |||
| 140 | const auto result = CreateAppletResourceImpl(aruid); | ||
| 141 | if (result.IsError()) { | ||
| 142 | return result; | ||
| 143 | } | ||
| 144 | |||
| 145 | // Homebrew doesn't try to activate some controllers, so we activate them by default | ||
| 146 | npad->Activate(); | ||
| 147 | six_axis->Activate(); | ||
| 148 | touch_screen->Activate(); | ||
| 149 | |||
| 150 | return GetNpad()->ActivateNpadResource(aruid); | ||
| 151 | } | ||
| 152 | |||
| 153 | Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { | ||
| 154 | std::scoped_lock lock{shared_mutex}; | ||
| 155 | return applet_resource->CreateAppletResource(aruid); | ||
| 156 | } | ||
| 157 | |||
| 158 | void ResourceManager::InitializeHidCommonSampler() { | ||
| 159 | debug_pad = std::make_shared<DebugPad>(system.HIDCore()); | ||
| 160 | mouse = std::make_shared<Mouse>(system.HIDCore()); | ||
| 161 | debug_mouse = std::make_shared<DebugMouse>(system.HIDCore()); | ||
| 162 | keyboard = std::make_shared<Keyboard>(system.HIDCore()); | ||
| 163 | unique_pad = std::make_shared<UniquePad>(system.HIDCore()); | ||
| 164 | npad = std::make_shared<NPad>(system.HIDCore(), service_context); | ||
| 165 | gesture = std::make_shared<Gesture>(system.HIDCore()); | ||
| 166 | home_button = std::make_shared<HomeButton>(system.HIDCore()); | ||
| 167 | sleep_button = std::make_shared<SleepButton>(system.HIDCore()); | ||
| 168 | capture_button = std::make_shared<CaptureButton>(system.HIDCore()); | ||
| 169 | digitizer = std::make_shared<Digitizer>(system.HIDCore()); | ||
| 170 | |||
| 171 | palma = std::make_shared<Palma>(system.HIDCore(), service_context); | ||
| 172 | six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad); | ||
| 173 | |||
| 174 | debug_pad->SetAppletResource(applet_resource, &shared_mutex); | ||
| 175 | digitizer->SetAppletResource(applet_resource, &shared_mutex); | ||
| 176 | keyboard->SetAppletResource(applet_resource, &shared_mutex); | ||
| 177 | npad->SetNpadExternals(applet_resource, &shared_mutex); | ||
| 178 | six_axis->SetAppletResource(applet_resource, &shared_mutex); | ||
| 179 | mouse->SetAppletResource(applet_resource, &shared_mutex); | ||
| 180 | debug_mouse->SetAppletResource(applet_resource, &shared_mutex); | ||
| 181 | home_button->SetAppletResource(applet_resource, &shared_mutex); | ||
| 182 | sleep_button->SetAppletResource(applet_resource, &shared_mutex); | ||
| 183 | capture_button->SetAppletResource(applet_resource, &shared_mutex); | ||
| 184 | } | ||
| 185 | |||
| 186 | void ResourceManager::InitializeTouchScreenSampler() { | ||
| 187 | gesture = std::make_shared<Gesture>(system.HIDCore()); | ||
| 188 | touch_screen = std::make_shared<TouchScreen>(system.HIDCore()); | ||
| 189 | |||
| 190 | touch_screen->SetAppletResource(applet_resource, &shared_mutex); | ||
| 191 | gesture->SetAppletResource(applet_resource, &shared_mutex); | ||
| 192 | } | ||
| 193 | |||
| 194 | void ResourceManager::InitializeConsoleSixAxisSampler() { | ||
| 195 | console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore()); | ||
| 196 | seven_six_axis = std::make_shared<SevenSixAxis>(system); | ||
| 197 | |||
| 198 | console_six_axis->SetAppletResource(applet_resource, &shared_mutex); | ||
| 199 | } | ||
| 200 | |||
| 201 | void ResourceManager::InitializeAHidSampler() { | ||
| 202 | // TODO | ||
| 203 | } | ||
| 204 | |||
| 205 | Result ResourceManager::RegisterCoreAppletResource() { | ||
| 206 | std::scoped_lock lock{shared_mutex}; | ||
| 207 | return applet_resource->RegisterCoreAppletResource(); | ||
| 208 | } | ||
| 209 | |||
| 210 | Result ResourceManager::UnregisterCoreAppletResource() { | ||
| 211 | std::scoped_lock lock{shared_mutex}; | ||
| 212 | return applet_resource->UnregisterCoreAppletResource(); | ||
| 213 | } | ||
| 214 | |||
| 215 | Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) { | ||
| 216 | std::scoped_lock lock{shared_mutex}; | ||
| 217 | auto result = applet_resource->RegisterAppletResourceUserId(aruid, bool_value); | ||
| 218 | if (result.IsSuccess()) { | ||
| 219 | result = npad->RegisterAppletResourceUserId(aruid); | ||
| 220 | } | ||
| 221 | return result; | ||
| 222 | } | ||
| 223 | |||
| 224 | void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 225 | std::scoped_lock lock{shared_mutex}; | ||
| 226 | applet_resource->UnregisterAppletResourceUserId(aruid); | ||
| 227 | } | ||
| 228 | |||
| 229 | Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { | ||
| 230 | std::scoped_lock lock{shared_mutex}; | ||
| 231 | return applet_resource->GetSharedMemoryHandle(out_handle, aruid); | ||
| 232 | } | ||
| 233 | |||
| 234 | void ResourceManager::FreeAppletResourceId(u64 aruid) { | ||
| 235 | std::scoped_lock lock{shared_mutex}; | ||
| 236 | applet_resource->FreeAppletResourceId(aruid); | ||
| 237 | } | ||
| 238 | |||
| 239 | void ResourceManager::EnableInput(u64 aruid, bool is_enabled) { | ||
| 240 | std::scoped_lock lock{shared_mutex}; | ||
| 241 | applet_resource->EnableInput(aruid, is_enabled); | ||
| 242 | } | ||
| 243 | |||
| 244 | void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) { | ||
| 245 | std::scoped_lock lock{shared_mutex}; | ||
| 246 | applet_resource->EnableSixAxisSensor(aruid, is_enabled); | ||
| 247 | } | ||
| 248 | |||
| 249 | void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) { | ||
| 250 | std::scoped_lock lock{shared_mutex}; | ||
| 251 | applet_resource->EnablePadInput(aruid, is_enabled); | ||
| 252 | } | ||
| 253 | |||
| 254 | void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { | ||
| 255 | std::scoped_lock lock{shared_mutex}; | ||
| 256 | applet_resource->EnableTouchScreen(aruid, is_enabled); | ||
| 257 | } | ||
| 258 | |||
| 259 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { | ||
| 260 | auto& core_timing = system.CoreTiming(); | ||
| 261 | debug_pad->OnUpdate(core_timing); | ||
| 262 | digitizer->OnUpdate(core_timing); | ||
| 263 | unique_pad->OnUpdate(core_timing); | ||
| 264 | gesture->OnUpdate(core_timing); | ||
| 265 | touch_screen->OnUpdate(core_timing); | ||
| 266 | palma->OnUpdate(core_timing); | ||
| 267 | home_button->OnUpdate(core_timing); | ||
| 268 | sleep_button->OnUpdate(core_timing); | ||
| 269 | capture_button->OnUpdate(core_timing); | ||
| 270 | } | ||
| 271 | |||
| 272 | void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) { | ||
| 273 | auto& core_timing = system.CoreTiming(); | ||
| 274 | npad->OnUpdate(core_timing); | ||
| 275 | } | ||
| 276 | |||
| 277 | void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) { | ||
| 278 | auto& core_timing = system.CoreTiming(); | ||
| 279 | mouse->OnUpdate(core_timing); | ||
| 280 | debug_mouse->OnUpdate(core_timing); | ||
| 281 | keyboard->OnUpdate(core_timing); | ||
| 282 | } | ||
| 283 | |||
| 284 | void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) { | ||
| 285 | auto& core_timing = system.CoreTiming(); | ||
| 286 | six_axis->OnUpdate(core_timing); | ||
| 287 | seven_six_axis->OnUpdate(core_timing); | ||
| 288 | console_six_axis->OnUpdate(core_timing); | ||
| 289 | } | ||
| 290 | |||
| 291 | IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, | ||
| 292 | u64 applet_resource_user_id) | ||
| 293 | : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id}, | ||
| 294 | resource_manager{resource} { | ||
| 295 | static const FunctionInfo functions[] = { | ||
| 296 | {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, | ||
| 297 | }; | ||
| 298 | RegisterHandlers(functions); | ||
| 299 | |||
| 300 | // Register update callbacks | ||
| 301 | npad_update_event = Core::Timing::CreateEvent( | ||
| 302 | "HID::UpdatePadCallback", | ||
| 303 | [this, resource]( | ||
| 304 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 305 | const auto guard = LockService(); | ||
| 306 | resource->UpdateNpad(ns_late); | ||
| 307 | return std::nullopt; | ||
| 308 | }); | ||
| 309 | default_update_event = Core::Timing::CreateEvent( | ||
| 310 | "HID::UpdateDefaultCallback", | ||
| 311 | [this, resource]( | ||
| 312 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 313 | const auto guard = LockService(); | ||
| 314 | resource->UpdateControllers(ns_late); | ||
| 315 | return std::nullopt; | ||
| 316 | }); | ||
| 317 | mouse_keyboard_update_event = Core::Timing::CreateEvent( | ||
| 318 | "HID::UpdateMouseKeyboardCallback", | ||
| 319 | [this, resource]( | ||
| 320 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 321 | const auto guard = LockService(); | ||
| 322 | resource->UpdateMouseKeyboard(ns_late); | ||
| 323 | return std::nullopt; | ||
| 324 | }); | ||
| 325 | motion_update_event = Core::Timing::CreateEvent( | ||
| 326 | "HID::UpdateMotionCallback", | ||
| 327 | [this, resource]( | ||
| 328 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 329 | const auto guard = LockService(); | ||
| 330 | resource->UpdateMotion(ns_late); | ||
| 331 | return std::nullopt; | ||
| 332 | }); | ||
| 333 | |||
| 334 | system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event); | ||
| 335 | system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns, | ||
| 336 | default_update_event); | ||
| 337 | system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, | ||
| 338 | mouse_keyboard_update_event); | ||
| 339 | system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, | ||
| 340 | motion_update_event); | ||
| 341 | } | ||
| 342 | |||
| 343 | IAppletResource::~IAppletResource() { | ||
| 344 | system.CoreTiming().UnscheduleEvent(npad_update_event); | ||
| 345 | system.CoreTiming().UnscheduleEvent(default_update_event); | ||
| 346 | system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event); | ||
| 347 | system.CoreTiming().UnscheduleEvent(motion_update_event); | ||
| 348 | resource_manager->FreeAppletResourceId(aruid); | ||
| 349 | } | ||
| 350 | |||
| 351 | void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { | ||
| 352 | Kernel::KSharedMemory* handle; | ||
| 353 | const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid); | ||
| 354 | |||
| 355 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw); | ||
| 356 | |||
| 357 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 358 | rb.Push(result); | ||
| 359 | rb.PushCopyObjects(handle); | ||
| 360 | } | ||
| 361 | |||
| 362 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h deleted file mode 100644 index 7a21d8eb8..000000000 --- a/src/core/hle/service/hid/resource_manager.h +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Core { | ||
| 10 | class System; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Core::Timing { | ||
| 14 | struct EventType; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Kernel { | ||
| 18 | class KSharedMemory; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Service::HID { | ||
| 22 | class AppletResource; | ||
| 23 | class CaptureButton; | ||
| 24 | class Controller_Stubbed; | ||
| 25 | class ConsoleSixAxis; | ||
| 26 | class DebugMouse; | ||
| 27 | class DebugPad; | ||
| 28 | class Digitizer; | ||
| 29 | class Gesture; | ||
| 30 | class HomeButton; | ||
| 31 | class Keyboard; | ||
| 32 | class Mouse; | ||
| 33 | class NPad; | ||
| 34 | class Palma; | ||
| 35 | class SevenSixAxis; | ||
| 36 | class SixAxis; | ||
| 37 | class SleepButton; | ||
| 38 | class TouchScreen; | ||
| 39 | class UniquePad; | ||
| 40 | |||
| 41 | class ResourceManager { | ||
| 42 | |||
| 43 | public: | ||
| 44 | explicit ResourceManager(Core::System& system_); | ||
| 45 | ~ResourceManager(); | ||
| 46 | |||
| 47 | void Initialize(); | ||
| 48 | |||
| 49 | std::shared_ptr<AppletResource> GetAppletResource() const; | ||
| 50 | std::shared_ptr<CaptureButton> GetCaptureButton() const; | ||
| 51 | std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const; | ||
| 52 | std::shared_ptr<DebugMouse> GetDebugMouse() const; | ||
| 53 | std::shared_ptr<DebugPad> GetDebugPad() const; | ||
| 54 | std::shared_ptr<Digitizer> GetDigitizer() const; | ||
| 55 | std::shared_ptr<Gesture> GetGesture() const; | ||
| 56 | std::shared_ptr<HomeButton> GetHomeButton() const; | ||
| 57 | std::shared_ptr<Keyboard> GetKeyboard() const; | ||
| 58 | std::shared_ptr<Mouse> GetMouse() const; | ||
| 59 | std::shared_ptr<NPad> GetNpad() const; | ||
| 60 | std::shared_ptr<Palma> GetPalma() const; | ||
| 61 | std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const; | ||
| 62 | std::shared_ptr<SixAxis> GetSixAxis() const; | ||
| 63 | std::shared_ptr<SleepButton> GetSleepButton() const; | ||
| 64 | std::shared_ptr<TouchScreen> GetTouchScreen() const; | ||
| 65 | std::shared_ptr<UniquePad> GetUniquePad() const; | ||
| 66 | |||
| 67 | Result CreateAppletResource(u64 aruid); | ||
| 68 | |||
| 69 | Result RegisterCoreAppletResource(); | ||
| 70 | Result UnregisterCoreAppletResource(); | ||
| 71 | Result RegisterAppletResourceUserId(u64 aruid, bool bool_value); | ||
| 72 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 73 | |||
| 74 | Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); | ||
| 75 | void FreeAppletResourceId(u64 aruid); | ||
| 76 | |||
| 77 | void EnableInput(u64 aruid, bool is_enabled); | ||
| 78 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); | ||
| 79 | void EnablePadInput(u64 aruid, bool is_enabled); | ||
| 80 | void EnableTouchScreen(u64 aruid, bool is_enabled); | ||
| 81 | |||
| 82 | void UpdateControllers(std::chrono::nanoseconds ns_late); | ||
| 83 | void UpdateNpad(std::chrono::nanoseconds ns_late); | ||
| 84 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); | ||
| 85 | void UpdateMotion(std::chrono::nanoseconds ns_late); | ||
| 86 | |||
| 87 | private: | ||
| 88 | Result CreateAppletResourceImpl(u64 aruid); | ||
| 89 | void InitializeHidCommonSampler(); | ||
| 90 | void InitializeTouchScreenSampler(); | ||
| 91 | void InitializeConsoleSixAxisSampler(); | ||
| 92 | void InitializeAHidSampler(); | ||
| 93 | |||
| 94 | bool is_initialized{false}; | ||
| 95 | |||
| 96 | mutable std::recursive_mutex shared_mutex; | ||
| 97 | std::shared_ptr<AppletResource> applet_resource = nullptr; | ||
| 98 | |||
| 99 | std::shared_ptr<CaptureButton> capture_button = nullptr; | ||
| 100 | std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr; | ||
| 101 | std::shared_ptr<DebugMouse> debug_mouse = nullptr; | ||
| 102 | std::shared_ptr<DebugPad> debug_pad = nullptr; | ||
| 103 | std::shared_ptr<Digitizer> digitizer = nullptr; | ||
| 104 | std::shared_ptr<Gesture> gesture = nullptr; | ||
| 105 | std::shared_ptr<HomeButton> home_button = nullptr; | ||
| 106 | std::shared_ptr<Keyboard> keyboard = nullptr; | ||
| 107 | std::shared_ptr<Mouse> mouse = nullptr; | ||
| 108 | std::shared_ptr<NPad> npad = nullptr; | ||
| 109 | std::shared_ptr<Palma> palma = nullptr; | ||
| 110 | std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr; | ||
| 111 | std::shared_ptr<SixAxis> six_axis = nullptr; | ||
| 112 | std::shared_ptr<SleepButton> sleep_button = nullptr; | ||
| 113 | std::shared_ptr<TouchScreen> touch_screen = nullptr; | ||
| 114 | std::shared_ptr<UniquePad> unique_pad = nullptr; | ||
| 115 | |||
| 116 | // TODO: Create these resources | ||
| 117 | // std::shared_ptr<AudioControl> audio_control = nullptr; | ||
| 118 | // std::shared_ptr<ButtonConfig> button_config = nullptr; | ||
| 119 | // std::shared_ptr<Config> config = nullptr; | ||
| 120 | // std::shared_ptr<Connection> connection = nullptr; | ||
| 121 | // std::shared_ptr<CustomConfig> custom_config = nullptr; | ||
| 122 | // std::shared_ptr<Digitizer> digitizer = nullptr; | ||
| 123 | // std::shared_ptr<Hdls> hdls = nullptr; | ||
| 124 | // std::shared_ptr<PlayReport> play_report = nullptr; | ||
| 125 | // std::shared_ptr<Rail> rail = nullptr; | ||
| 126 | |||
| 127 | Core::System& system; | ||
| 128 | KernelHelpers::ServiceContext service_context; | ||
| 129 | }; | ||
| 130 | |||
| 131 | class IAppletResource final : public ServiceFramework<IAppletResource> { | ||
| 132 | public: | ||
| 133 | explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, | ||
| 134 | u64 applet_resource_user_id); | ||
| 135 | ~IAppletResource() override; | ||
| 136 | |||
| 137 | private: | ||
| 138 | void GetSharedMemoryHandle(HLERequestContext& ctx); | ||
| 139 | |||
| 140 | std::shared_ptr<Core::Timing::EventType> npad_update_event; | ||
| 141 | std::shared_ptr<Core::Timing::EventType> default_update_event; | ||
| 142 | std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; | ||
| 143 | std::shared_ptr<Core::Timing::EventType> motion_update_event; | ||
| 144 | |||
| 145 | u64 aruid; | ||
| 146 | std::shared_ptr<ResourceManager> resource_manager; | ||
| 147 | }; | ||
| 148 | |||
| 149 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h deleted file mode 100644 index 0816784e0..000000000 --- a/src/core/hle/service/hid/ring_lifo.h +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | template <typename State> | ||
| 13 | struct AtomicStorage { | ||
| 14 | s64 sampling_number; | ||
| 15 | State state; | ||
| 16 | }; | ||
| 17 | |||
| 18 | template <typename State, std::size_t max_buffer_size> | ||
| 19 | struct Lifo { | ||
| 20 | s64 timestamp{}; | ||
| 21 | s64 total_buffer_count = static_cast<s64>(max_buffer_size); | ||
| 22 | s64 buffer_tail{}; | ||
| 23 | s64 buffer_count{}; | ||
| 24 | std::array<AtomicStorage<State>, max_buffer_size> entries{}; | ||
| 25 | |||
| 26 | const AtomicStorage<State>& ReadCurrentEntry() const { | ||
| 27 | return entries[buffer_tail]; | ||
| 28 | } | ||
| 29 | |||
| 30 | const AtomicStorage<State>& ReadPreviousEntry() const { | ||
| 31 | return entries[GetPreviousEntryIndex()]; | ||
| 32 | } | ||
| 33 | |||
| 34 | std::size_t GetPreviousEntryIndex() const { | ||
| 35 | return static_cast<size_t>((buffer_tail + max_buffer_size - 1) % max_buffer_size); | ||
| 36 | } | ||
| 37 | |||
| 38 | std::size_t GetNextEntryIndex() const { | ||
| 39 | return static_cast<size_t>((buffer_tail + 1) % max_buffer_size); | ||
| 40 | } | ||
| 41 | |||
| 42 | void WriteNextEntry(const State& new_state) { | ||
| 43 | if (buffer_count < static_cast<s64>(max_buffer_size) - 1) { | ||
| 44 | buffer_count++; | ||
| 45 | } | ||
| 46 | buffer_tail = GetNextEntryIndex(); | ||
| 47 | const auto& previous_entry = ReadPreviousEntry(); | ||
| 48 | entries[buffer_tail].sampling_number = previous_entry.sampling_number + 1; | ||
| 49 | entries[buffer_tail].state = new_state; | ||
| 50 | } | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index f97e5b44c..b37fb6da3 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -22,9 +22,6 @@ | |||
| 22 | #include "common/string_util.h" | 22 | #include "common/string_util.h" |
| 23 | #include "common/tiny_mt.h" | 23 | #include "common/tiny_mt.h" |
| 24 | #include "core/core.h" | 24 | #include "core/core.h" |
| 25 | #include "core/hid/emulated_controller.h" | ||
| 26 | #include "core/hid/hid_core.h" | ||
| 27 | #include "core/hid/hid_types.h" | ||
| 28 | #include "core/hle/kernel/k_event.h" | 25 | #include "core/hle/kernel/k_event.h" |
| 29 | #include "core/hle/service/ipc_helpers.h" | 26 | #include "core/hle/service/ipc_helpers.h" |
| 30 | #include "core/hle/service/mii/mii_manager.h" | 27 | #include "core/hle/service/mii/mii_manager.h" |
| @@ -33,6 +30,9 @@ | |||
| 33 | #include "core/hle/service/nfc/mifare_result.h" | 30 | #include "core/hle/service/nfc/mifare_result.h" |
| 34 | #include "core/hle/service/nfc/nfc_result.h" | 31 | #include "core/hle/service/nfc/nfc_result.h" |
| 35 | #include "core/hle/service/time/time_manager.h" | 32 | #include "core/hle/service/time/time_manager.h" |
| 33 | #include "hid_core/frontend/emulated_controller.h" | ||
| 34 | #include "hid_core/hid_core.h" | ||
| 35 | #include "hid_core/hid_types.h" | ||
| 36 | 36 | ||
| 37 | namespace Service::NFC { | 37 | namespace Service::NFC { |
| 38 | NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, | 38 | NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, |
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index ad534177d..44f651b87 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp | |||
| @@ -5,15 +5,15 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/service/hid/hid_util.h" | ||
| 11 | #include "core/hle/service/ipc_helpers.h" | 9 | #include "core/hle/service/ipc_helpers.h" |
| 12 | #include "core/hle/service/nfc/common/device.h" | 10 | #include "core/hle/service/nfc/common/device.h" |
| 13 | #include "core/hle/service/nfc/common/device_manager.h" | 11 | #include "core/hle/service/nfc/common/device_manager.h" |
| 14 | #include "core/hle/service/nfc/nfc_result.h" | 12 | #include "core/hle/service/nfc/nfc_result.h" |
| 15 | #include "core/hle/service/time/clock_types.h" | 13 | #include "core/hle/service/time/clock_types.h" |
| 16 | #include "core/hle/service/time/time_manager.h" | 14 | #include "core/hle/service/time/time_manager.h" |
| 15 | #include "hid_core/hid_types.h" | ||
| 16 | #include "hid_core/hid_util.h" | ||
| 17 | 17 | ||
| 18 | namespace Service::NFC { | 18 | namespace Service::NFC { |
| 19 | 19 | ||
diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h index c9f038e32..f02bdccf5 100644 --- a/src/core/hle/service/nfc/common/device_manager.h +++ b/src/core/hle/service/nfc/common/device_manager.h | |||
| @@ -8,13 +8,13 @@ | |||
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <span> | 9 | #include <span> |
| 10 | 10 | ||
| 11 | #include "core/hid/hid_types.h" | ||
| 12 | #include "core/hle/service/kernel_helpers.h" | 11 | #include "core/hle/service/kernel_helpers.h" |
| 13 | #include "core/hle/service/nfc/mifare_types.h" | 12 | #include "core/hle/service/nfc/mifare_types.h" |
| 14 | #include "core/hle/service/nfc/nfc_types.h" | 13 | #include "core/hle/service/nfc/nfc_types.h" |
| 15 | #include "core/hle/service/nfp/nfp_types.h" | 14 | #include "core/hle/service/nfp/nfp_types.h" |
| 16 | #include "core/hle/service/service.h" | 15 | #include "core/hle/service/service.h" |
| 17 | #include "core/hle/service/time/clock_types.h" | 16 | #include "core/hle/service/time/clock_types.h" |
| 17 | #include "hid_core/hid_types.h" | ||
| 18 | 18 | ||
| 19 | namespace Service::NFC { | 19 | namespace Service::NFC { |
| 20 | class NfcDevice; | 20 | class NfcDevice; |
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 179c7ba2c..a71cf74b8 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | 6 | #include "core/hle/kernel/k_event.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/nfc/common/device.h" | 8 | #include "core/hle/service/nfc/common/device.h" |
| @@ -15,6 +14,7 @@ | |||
| 15 | #include "core/hle/service/nfc/nfc_types.h" | 14 | #include "core/hle/service/nfc/nfc_types.h" |
| 16 | #include "core/hle/service/nfp/nfp_result.h" | 15 | #include "core/hle/service/nfp/nfp_result.h" |
| 17 | #include "core/hle/service/time/clock_types.h" | 16 | #include "core/hle/service/time/clock_types.h" |
| 17 | #include "hid_core/hid_types.h" | ||
| 18 | 18 | ||
| 19 | namespace Service::NFC { | 19 | namespace Service::NFC { |
| 20 | 20 | ||
diff --git a/src/core/hle/service/nfp/nfp_interface.cpp b/src/core/hle/service/nfp/nfp_interface.cpp index 34ef9d82d..5ba6d1742 100644 --- a/src/core/hle/service/nfp/nfp_interface.cpp +++ b/src/core/hle/service/nfp/nfp_interface.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | 6 | #include "core/hle/kernel/k_event.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/nfc/common/device.h" | 8 | #include "core/hle/service/nfc/common/device.h" |
| @@ -12,6 +11,7 @@ | |||
| 12 | #include "core/hle/service/nfp/nfp_interface.h" | 11 | #include "core/hle/service/nfp/nfp_interface.h" |
| 13 | #include "core/hle/service/nfp/nfp_result.h" | 12 | #include "core/hle/service/nfp/nfp_result.h" |
| 14 | #include "core/hle/service/nfp/nfp_types.h" | 13 | #include "core/hle/service/nfp/nfp_types.h" |
| 14 | #include "hid_core/hid_types.h" | ||
| 15 | 15 | ||
| 16 | namespace Service::NFP { | 16 | namespace Service::NFP { |
| 17 | 17 | ||