diff options
| author | 2024-02-01 11:33:44 -0500 | |
|---|---|---|
| committer | 2024-02-01 11:33:44 -0500 | |
| commit | 21138b6a867632c56330a48a7389430ae2b6e321 (patch) | |
| tree | 6be048ee977f29f4c132d0cfb0bcdb79a7c5966d | |
| parent | Merge pull request #12870 from liamwhite/mac-ci (diff) | |
| parent | service: hid: Restore active aruid (diff) | |
| download | yuzu-21138b6a867632c56330a48a7389430ae2b6e321.tar.gz yuzu-21138b6a867632c56330a48a7389430ae2b6e321.tar.xz yuzu-21138b6a867632c56330a48a7389430ae2b6e321.zip | |
Merge pull request #12780 from german77/touch_resource5
service: hid: Fully implement touch resource
32 files changed, 1894 insertions, 739 deletions
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 5b28be577..b60fb9139 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -18,9 +18,10 @@ namespace Service::HID { | |||
| 18 | 18 | ||
| 19 | void LoopProcess(Core::System& system) { | 19 | void LoopProcess(Core::System& system) { |
| 20 | auto server_manager = std::make_unique<ServerManager>(system); | 20 | auto server_manager = std::make_unique<ServerManager>(system); |
| 21 | std::shared_ptr<ResourceManager> resource_manager = std::make_shared<ResourceManager>(system); | ||
| 22 | std::shared_ptr<HidFirmwareSettings> firmware_settings = | 21 | std::shared_ptr<HidFirmwareSettings> firmware_settings = |
| 23 | std::make_shared<HidFirmwareSettings>(system); | 22 | std::make_shared<HidFirmwareSettings>(system); |
| 23 | std::shared_ptr<ResourceManager> resource_manager = | ||
| 24 | std::make_shared<ResourceManager>(system, firmware_settings); | ||
| 24 | 25 | ||
| 25 | // TODO: Remove this hack when am is emulated properly. | 26 | // TODO: Remove this hack when am is emulated properly. |
| 26 | resource_manager->Initialize(); | 27 | resource_manager->Initialize(); |
| @@ -31,7 +32,7 @@ void LoopProcess(Core::System& system) { | |||
| 31 | server_manager->RegisterNamedService( | 32 | server_manager->RegisterNamedService( |
| 32 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); | 33 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); |
| 33 | server_manager->RegisterNamedService( | 34 | server_manager->RegisterNamedService( |
| 34 | "hid:dbg", std::make_shared<IHidDebugServer>(system, resource_manager)); | 35 | "hid:dbg", std::make_shared<IHidDebugServer>(system, resource_manager, firmware_settings)); |
| 35 | server_manager->RegisterNamedService( | 36 | server_manager->RegisterNamedService( |
| 36 | "hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager, firmware_settings)); | 37 | "hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager, firmware_settings)); |
| 37 | 38 | ||
diff --git a/src/core/hle/service/hid/hid_debug_server.cpp b/src/core/hle/service/hid/hid_debug_server.cpp index f2a767d37..610af34dd 100644 --- a/src/core/hle/service/hid/hid_debug_server.cpp +++ b/src/core/hle/service/hid/hid_debug_server.cpp | |||
| @@ -1,27 +1,37 @@ | |||
| 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 <algorithm> | ||
| 5 | |||
| 4 | #include "core/hle/service/hid/hid_debug_server.h" | 6 | #include "core/hle/service/hid/hid_debug_server.h" |
| 5 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 8 | #include "hid_core/hid_types.h" | ||
| 6 | #include "hid_core/resource_manager.h" | 9 | #include "hid_core/resource_manager.h" |
| 10 | #include "hid_core/resources/hid_firmware_settings.h" | ||
| 11 | |||
| 12 | #include "hid_core/resources/touch_screen/gesture.h" | ||
| 13 | #include "hid_core/resources/touch_screen/touch_screen.h" | ||
| 14 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 7 | 15 | ||
| 8 | namespace Service::HID { | 16 | namespace Service::HID { |
| 9 | 17 | ||
| 10 | IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource) | 18 | IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource, |
| 11 | : ServiceFramework{system_, "hid:dbg"}, resource_manager{resource} { | 19 | std::shared_ptr<HidFirmwareSettings> settings) |
| 20 | : ServiceFramework{system_, "hid:dbg"}, resource_manager{resource}, firmware_settings{ | ||
| 21 | settings} { | ||
| 12 | // clang-format off | 22 | // clang-format off |
| 13 | static const FunctionInfo functions[] = { | 23 | static const FunctionInfo functions[] = { |
| 14 | {0, nullptr, "DeactivateDebugPad"}, | 24 | {0, nullptr, "DeactivateDebugPad"}, |
| 15 | {1, nullptr, "SetDebugPadAutoPilotState"}, | 25 | {1, nullptr, "SetDebugPadAutoPilotState"}, |
| 16 | {2, nullptr, "UnsetDebugPadAutoPilotState"}, | 26 | {2, nullptr, "UnsetDebugPadAutoPilotState"}, |
| 17 | {10, nullptr, "DeactivateTouchScreen"}, | 27 | {10, &IHidDebugServer::DeactivateTouchScreen, "DeactivateTouchScreen"}, |
| 18 | {11, nullptr, "SetTouchScreenAutoPilotState"}, | 28 | {11, &IHidDebugServer::SetTouchScreenAutoPilotState, "SetTouchScreenAutoPilotState"}, |
| 19 | {12, nullptr, "UnsetTouchScreenAutoPilotState"}, | 29 | {12, &IHidDebugServer::UnsetTouchScreenAutoPilotState, "UnsetTouchScreenAutoPilotState"}, |
| 20 | {13, nullptr, "GetTouchScreenConfiguration"}, | 30 | {13, &IHidDebugServer::GetTouchScreenConfiguration, "GetTouchScreenConfiguration"}, |
| 21 | {14, nullptr, "ProcessTouchScreenAutoTune"}, | 31 | {14, &IHidDebugServer::ProcessTouchScreenAutoTune, "ProcessTouchScreenAutoTune"}, |
| 22 | {15, nullptr, "ForceStopTouchScreenManagement"}, | 32 | {15, &IHidDebugServer::ForceStopTouchScreenManagement, "ForceStopTouchScreenManagement"}, |
| 23 | {16, nullptr, "ForceRestartTouchScreenManagement"}, | 33 | {16, &IHidDebugServer::ForceRestartTouchScreenManagement, "ForceRestartTouchScreenManagement"}, |
| 24 | {17, nullptr, "IsTouchScreenManaged"}, | 34 | {17, &IHidDebugServer::IsTouchScreenManaged, "IsTouchScreenManaged"}, |
| 25 | {20, nullptr, "DeactivateMouse"}, | 35 | {20, nullptr, "DeactivateMouse"}, |
| 26 | {21, nullptr, "SetMouseAutoPilotState"}, | 36 | {21, nullptr, "SetMouseAutoPilotState"}, |
| 27 | {22, nullptr, "UnsetMouseAutoPilotState"}, | 37 | {22, nullptr, "UnsetMouseAutoPilotState"}, |
| @@ -37,7 +47,7 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource | |||
| 37 | {60, nullptr, "ClearNpadSystemCommonPolicy"}, | 47 | {60, nullptr, "ClearNpadSystemCommonPolicy"}, |
| 38 | {61, nullptr, "DeactivateNpad"}, | 48 | {61, nullptr, "DeactivateNpad"}, |
| 39 | {62, nullptr, "ForceDisconnectNpad"}, | 49 | {62, nullptr, "ForceDisconnectNpad"}, |
| 40 | {91, nullptr, "DeactivateGesture"}, | 50 | {91, &IHidDebugServer::DeactivateGesture, "DeactivateGesture"}, |
| 41 | {110, nullptr, "DeactivateHomeButton"}, | 51 | {110, nullptr, "DeactivateHomeButton"}, |
| 42 | {111, nullptr, "SetHomeButtonAutoPilotState"}, | 52 | {111, nullptr, "SetHomeButtonAutoPilotState"}, |
| 43 | {112, nullptr, "UnsetHomeButtonAutoPilotState"}, | 53 | {112, nullptr, "UnsetHomeButtonAutoPilotState"}, |
| @@ -150,6 +160,170 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource | |||
| 150 | } | 160 | } |
| 151 | 161 | ||
| 152 | IHidDebugServer::~IHidDebugServer() = default; | 162 | IHidDebugServer::~IHidDebugServer() = default; |
| 163 | void IHidDebugServer::DeactivateTouchScreen(HLERequestContext& ctx) { | ||
| 164 | LOG_INFO(Service_HID, "called"); | ||
| 165 | |||
| 166 | Result result = ResultSuccess; | ||
| 167 | |||
| 168 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 169 | result = GetResourceManager()->GetTouchScreen()->Deactivate(); | ||
| 170 | } | ||
| 171 | |||
| 172 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 173 | rb.Push(result); | ||
| 174 | } | ||
| 175 | |||
| 176 | void IHidDebugServer::SetTouchScreenAutoPilotState(HLERequestContext& ctx) { | ||
| 177 | AutoPilotState auto_pilot{}; | ||
| 178 | auto_pilot.count = ctx.GetReadBufferNumElements<TouchState>(); | ||
| 179 | const auto buffer = ctx.ReadBuffer(); | ||
| 180 | |||
| 181 | auto_pilot.count = std::min(auto_pilot.count, static_cast<u64>(auto_pilot.state.size())); | ||
| 182 | memcpy(auto_pilot.state.data(), buffer.data(), auto_pilot.count * sizeof(TouchState)); | ||
| 183 | |||
| 184 | LOG_INFO(Service_HID, "called, auto_pilot_count={}", auto_pilot.count); | ||
| 185 | |||
| 186 | const Result result = | ||
| 187 | GetResourceManager()->GetTouchScreen()->SetTouchScreenAutoPilotState(auto_pilot); | ||
| 188 | |||
| 189 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 190 | rb.Push(result); | ||
| 191 | } | ||
| 192 | |||
| 193 | void IHidDebugServer::UnsetTouchScreenAutoPilotState(HLERequestContext& ctx) { | ||
| 194 | LOG_INFO(Service_HID, "called"); | ||
| 195 | |||
| 196 | const Result result = GetResourceManager()->GetTouchScreen()->UnsetTouchScreenAutoPilotState(); | ||
| 197 | |||
| 198 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 199 | rb.Push(result); | ||
| 200 | } | ||
| 201 | |||
| 202 | void IHidDebugServer::GetTouchScreenConfiguration(HLERequestContext& ctx) { | ||
| 203 | IPC::RequestParser rp{ctx}; | ||
| 204 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 205 | |||
| 206 | LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 207 | |||
| 208 | Core::HID::TouchScreenConfigurationForNx touchscreen_config{}; | ||
| 209 | const Result result = GetResourceManager()->GetTouchScreen()->GetTouchScreenConfiguration( | ||
| 210 | touchscreen_config, applet_resource_user_id); | ||
| 211 | |||
| 212 | if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && | ||
| 213 | touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { | ||
| 214 | touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting; | ||
| 215 | } | ||
| 216 | |||
| 217 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 218 | rb.Push(result); | ||
| 219 | rb.PushRaw(touchscreen_config); | ||
| 220 | } | ||
| 221 | |||
| 222 | void IHidDebugServer::ProcessTouchScreenAutoTune(HLERequestContext& ctx) { | ||
| 223 | LOG_INFO(Service_HID, "called"); | ||
| 224 | |||
| 225 | Result result = GetResourceManager()->GetTouchScreen()->ProcessTouchScreenAutoTune(); | ||
| 226 | |||
| 227 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 228 | rb.Push(result); | ||
| 229 | } | ||
| 230 | |||
| 231 | void IHidDebugServer::ForceStopTouchScreenManagement(HLERequestContext& ctx) { | ||
| 232 | LOG_INFO(Service_HID, "called"); | ||
| 233 | |||
| 234 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 235 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 236 | rb.Push(ResultSuccess); | ||
| 237 | return; | ||
| 238 | } | ||
| 239 | |||
| 240 | Result result = ResultSuccess; | ||
| 241 | bool is_touch_active{}; | ||
| 242 | bool is_gesture_active{}; | ||
| 243 | auto touch_screen = GetResourceManager()->GetTouchScreen(); | ||
| 244 | auto gesture = GetResourceManager()->GetGesture(); | ||
| 245 | |||
| 246 | if (firmware_settings->IsTouchI2cManaged()) { | ||
| 247 | result = touch_screen->IsActive(is_touch_active); | ||
| 248 | if (result.IsSuccess()) { | ||
| 249 | result = gesture->IsActive(is_gesture_active); | ||
| 250 | } | ||
| 251 | if (result.IsSuccess() && is_touch_active) { | ||
| 252 | result = touch_screen->Deactivate(); | ||
| 253 | } | ||
| 254 | if (result.IsSuccess() && is_gesture_active) { | ||
| 255 | result = gesture->Deactivate(); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 260 | rb.Push(result); | ||
| 261 | } | ||
| 262 | |||
| 263 | void IHidDebugServer::ForceRestartTouchScreenManagement(HLERequestContext& ctx) { | ||
| 264 | IPC::RequestParser rp{ctx}; | ||
| 265 | struct Parameters { | ||
| 266 | u32 basic_gesture_id; | ||
| 267 | INSERT_PADDING_WORDS_NOINIT(1); | ||
| 268 | u64 applet_resource_user_id; | ||
| 269 | }; | ||
| 270 | static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||
| 271 | |||
| 272 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 273 | |||
| 274 | LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}", | ||
| 275 | parameters.basic_gesture_id, parameters.applet_resource_user_id); | ||
| 276 | |||
| 277 | Result result = ResultSuccess; | ||
| 278 | auto touch_screen = GetResourceManager()->GetTouchScreen(); | ||
| 279 | auto gesture = GetResourceManager()->GetGesture(); | ||
| 280 | |||
| 281 | if (firmware_settings->IsDeviceManaged() && firmware_settings->IsTouchI2cManaged()) { | ||
| 282 | result = gesture->Activate(); | ||
| 283 | if (result.IsSuccess()) { | ||
| 284 | result = | ||
| 285 | gesture->Activate(parameters.applet_resource_user_id, parameters.basic_gesture_id); | ||
| 286 | } | ||
| 287 | if (result.IsSuccess()) { | ||
| 288 | result = touch_screen->Activate(); | ||
| 289 | } | ||
| 290 | if (result.IsSuccess()) { | ||
| 291 | result = touch_screen->Activate(parameters.applet_resource_user_id); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 296 | rb.Push(result); | ||
| 297 | } | ||
| 298 | |||
| 299 | void IHidDebugServer::IsTouchScreenManaged(HLERequestContext& ctx) { | ||
| 300 | LOG_INFO(Service_HID, "called"); | ||
| 301 | |||
| 302 | bool is_touch_active{}; | ||
| 303 | bool is_gesture_active{}; | ||
| 304 | |||
| 305 | Result result = GetResourceManager()->GetTouchScreen()->IsActive(is_touch_active); | ||
| 306 | if (result.IsSuccess()) { | ||
| 307 | result = GetResourceManager()->GetGesture()->IsActive(is_gesture_active); | ||
| 308 | } | ||
| 309 | |||
| 310 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 311 | rb.Push(result); | ||
| 312 | rb.Push(is_touch_active | is_gesture_active); | ||
| 313 | } | ||
| 314 | |||
| 315 | void IHidDebugServer::DeactivateGesture(HLERequestContext& ctx) { | ||
| 316 | LOG_INFO(Service_HID, "called"); | ||
| 317 | |||
| 318 | Result result = ResultSuccess; | ||
| 319 | |||
| 320 | if (!firmware_settings->IsDeviceManaged()) { | ||
| 321 | result = GetResourceManager()->GetGesture()->Deactivate(); | ||
| 322 | } | ||
| 323 | |||
| 324 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 325 | rb.Push(result); | ||
| 326 | } | ||
| 153 | 327 | ||
| 154 | std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() { | 328 | std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() { |
| 155 | resource_manager->Initialize(); | 329 | resource_manager->Initialize(); |
diff --git a/src/core/hle/service/hid/hid_debug_server.h b/src/core/hle/service/hid/hid_debug_server.h index 406db2211..7d5b082b3 100644 --- a/src/core/hle/service/hid/hid_debug_server.h +++ b/src/core/hle/service/hid/hid_debug_server.h | |||
| @@ -11,16 +11,29 @@ class System; | |||
| 11 | 11 | ||
| 12 | namespace Service::HID { | 12 | namespace Service::HID { |
| 13 | class ResourceManager; | 13 | class ResourceManager; |
| 14 | class HidFirmwareSettings; | ||
| 14 | 15 | ||
| 15 | class IHidDebugServer final : public ServiceFramework<IHidDebugServer> { | 16 | class IHidDebugServer final : public ServiceFramework<IHidDebugServer> { |
| 16 | public: | 17 | public: |
| 17 | explicit IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource); | 18 | explicit IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource, |
| 19 | std::shared_ptr<HidFirmwareSettings> settings); | ||
| 18 | ~IHidDebugServer() override; | 20 | ~IHidDebugServer() override; |
| 19 | 21 | ||
| 20 | private: | 22 | private: |
| 23 | void DeactivateTouchScreen(HLERequestContext& ctx); | ||
| 24 | void SetTouchScreenAutoPilotState(HLERequestContext& ctx); | ||
| 25 | void UnsetTouchScreenAutoPilotState(HLERequestContext& ctx); | ||
| 26 | void GetTouchScreenConfiguration(HLERequestContext& ctx); | ||
| 27 | void ProcessTouchScreenAutoTune(HLERequestContext& ctx); | ||
| 28 | void ForceStopTouchScreenManagement(HLERequestContext& ctx); | ||
| 29 | void ForceRestartTouchScreenManagement(HLERequestContext& ctx); | ||
| 30 | void IsTouchScreenManaged(HLERequestContext& ctx); | ||
| 31 | void DeactivateGesture(HLERequestContext& ctx); | ||
| 32 | |||
| 21 | std::shared_ptr<ResourceManager> GetResourceManager(); | 33 | std::shared_ptr<ResourceManager> GetResourceManager(); |
| 22 | 34 | ||
| 23 | std::shared_ptr<ResourceManager> resource_manager; | 35 | std::shared_ptr<ResourceManager> resource_manager; |
| 36 | std::shared_ptr<HidFirmwareSettings> firmware_settings; | ||
| 24 | }; | 37 | }; |
| 25 | 38 | ||
| 26 | } // namespace Service::HID | 39 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 938b93451..3603d8ccf 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -990,8 +990,7 @@ void IHidServer::ActivateGesture(HLERequestContext& ctx) { | |||
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | if (result.IsSuccess()) { | 992 | if (result.IsSuccess()) { |
| 993 | // TODO: Use gesture id here | 993 | result = gesture->Activate(parameters.applet_resource_user_id, parameters.basic_gesture_id); |
| 994 | result = gesture->Activate(parameters.applet_resource_user_id); | ||
| 995 | } | 994 | } |
| 996 | 995 | ||
| 997 | IPC::ResponseBuilder rb{ctx, 2}; | 996 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -2470,14 +2469,22 @@ void IHidServer::GetNpadCommunicationMode(HLERequestContext& ctx) { | |||
| 2470 | 2469 | ||
| 2471 | void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) { | 2470 | void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) { |
| 2472 | IPC::RequestParser rp{ctx}; | 2471 | IPC::RequestParser rp{ctx}; |
| 2473 | const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()}; | 2472 | auto touchscreen_config{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()}; |
| 2474 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 2473 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 2475 | 2474 | ||
| 2476 | LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}", | 2475 | LOG_INFO(Service_HID, "called, touchscreen_config={}, applet_resource_user_id={}", |
| 2477 | touchscreen_mode.mode, applet_resource_user_id); | 2476 | touchscreen_config.mode, applet_resource_user_id); |
| 2477 | |||
| 2478 | if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && | ||
| 2479 | touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { | ||
| 2480 | touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting; | ||
| 2481 | } | ||
| 2482 | |||
| 2483 | const Result result = GetResourceManager()->GetTouchScreen()->SetTouchScreenConfiguration( | ||
| 2484 | touchscreen_config, applet_resource_user_id); | ||
| 2478 | 2485 | ||
| 2479 | IPC::ResponseBuilder rb{ctx, 2}; | 2486 | IPC::ResponseBuilder rb{ctx, 2}; |
| 2480 | rb.Push(ResultSuccess); | 2487 | rb.Push(result); |
| 2481 | } | 2488 | } |
| 2482 | 2489 | ||
| 2483 | void IHidServer::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) { | 2490 | void IHidServer::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) { |
| @@ -2505,11 +2512,12 @@ void IHidServer::SetTouchScreenResolution(HLERequestContext& ctx) { | |||
| 2505 | const auto height{rp.Pop<u32>()}; | 2512 | const auto height{rp.Pop<u32>()}; |
| 2506 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 2513 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 2507 | 2514 | ||
| 2508 | GetResourceManager()->GetTouchScreen()->SetTouchscreenDimensions(width, height); | ||
| 2509 | |||
| 2510 | LOG_INFO(Service_HID, "called, width={}, height={}, applet_resource_user_id={}", width, height, | 2515 | LOG_INFO(Service_HID, "called, width={}, height={}, applet_resource_user_id={}", width, height, |
| 2511 | applet_resource_user_id); | 2516 | applet_resource_user_id); |
| 2512 | 2517 | ||
| 2518 | GetResourceManager()->GetTouchScreen()->SetTouchScreenResolution(width, height, | ||
| 2519 | applet_resource_user_id); | ||
| 2520 | |||
| 2513 | IPC::ResponseBuilder rb{ctx, 2}; | 2521 | IPC::ResponseBuilder rb{ctx, 2}; |
| 2514 | rb.Push(ResultSuccess); | 2522 | rb.Push(ResultSuccess); |
| 2515 | } | 2523 | } |
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index d1ec42edc..22471e9e2 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp | |||
| @@ -155,9 +155,9 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour | |||
| 155 | {1133, nullptr, "StartUsbFirmwareUpdate"}, | 155 | {1133, nullptr, "StartUsbFirmwareUpdate"}, |
| 156 | {1134, nullptr, "GetUsbFirmwareUpdateState"}, | 156 | {1134, nullptr, "GetUsbFirmwareUpdateState"}, |
| 157 | {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"}, | 157 | {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"}, |
| 158 | {1150, nullptr, "SetTouchScreenMagnification"}, | 158 | {1150, &IHidSystemServer::SetTouchScreenMagnification, "SetTouchScreenMagnification"}, |
| 159 | {1151, nullptr, "GetTouchScreenFirmwareVersion"}, | 159 | {1151, &IHidSystemServer::GetTouchScreenFirmwareVersion, "GetTouchScreenFirmwareVersion"}, |
| 160 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, | 160 | {1152, &IHidSystemServer::SetTouchScreenDefaultConfiguration, "SetTouchScreenDefaultConfiguration"}, |
| 161 | {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, | 161 | {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, |
| 162 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, | 162 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, |
| 163 | {1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"}, | 163 | {1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"}, |
| @@ -845,12 +845,60 @@ void IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContex | |||
| 845 | rb.Push(ResultSuccess); | 845 | rb.Push(ResultSuccess); |
| 846 | } | 846 | } |
| 847 | 847 | ||
| 848 | void IHidSystemServer::SetTouchScreenMagnification(HLERequestContext& ctx) { | ||
| 849 | IPC::RequestParser rp{ctx}; | ||
| 850 | const auto point1x{rp.Pop<f32>()}; | ||
| 851 | const auto point1y{rp.Pop<f32>()}; | ||
| 852 | const auto point2x{rp.Pop<f32>()}; | ||
| 853 | const auto point2y{rp.Pop<f32>()}; | ||
| 854 | |||
| 855 | LOG_INFO(Service_HID, "called, point1=-({},{}), point2=({},{})", point1x, point1y, point2x, | ||
| 856 | point2y); | ||
| 857 | |||
| 858 | const Result result = GetResourceManager()->GetTouchScreen()->SetTouchScreenMagnification( | ||
| 859 | point1x, point1y, point2x, point2y); | ||
| 860 | |||
| 861 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 862 | rb.Push(result); | ||
| 863 | } | ||
| 864 | |||
| 865 | void IHidSystemServer::GetTouchScreenFirmwareVersion(HLERequestContext& ctx) { | ||
| 866 | LOG_INFO(Service_HID, "called"); | ||
| 867 | |||
| 868 | Core::HID::FirmwareVersion firmware{}; | ||
| 869 | const auto result = GetResourceManager()->GetTouchScreenFirmwareVersion(firmware); | ||
| 870 | |||
| 871 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 872 | rb.Push(result); | ||
| 873 | rb.PushRaw(firmware); | ||
| 874 | } | ||
| 875 | |||
| 876 | void IHidSystemServer::SetTouchScreenDefaultConfiguration(HLERequestContext& ctx) { | ||
| 877 | IPC::RequestParser rp{ctx}; | ||
| 878 | auto touchscreen_config{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()}; | ||
| 879 | |||
| 880 | LOG_INFO(Service_HID, "called, touchscreen_config={}", touchscreen_config.mode); | ||
| 881 | |||
| 882 | if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && | ||
| 883 | touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { | ||
| 884 | touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting; | ||
| 885 | } | ||
| 886 | |||
| 887 | const Result result = | ||
| 888 | GetResourceManager()->GetTouchScreen()->SetTouchScreenDefaultConfiguration( | ||
| 889 | touchscreen_config); | ||
| 890 | |||
| 891 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 892 | rb.Push(result); | ||
| 893 | } | ||
| 894 | |||
| 848 | void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) { | 895 | void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) { |
| 849 | LOG_WARNING(Service_HID, "(STUBBED) called"); | 896 | LOG_INFO(Service_HID, "called"); |
| 850 | 897 | ||
| 851 | Core::HID::TouchScreenConfigurationForNx touchscreen_config{ | 898 | Core::HID::TouchScreenConfigurationForNx touchscreen_config{}; |
| 852 | .mode = Core::HID::TouchScreenModeForNx::Finger, | 899 | const Result result = |
| 853 | }; | 900 | GetResourceManager()->GetTouchScreen()->GetTouchScreenDefaultConfiguration( |
| 901 | touchscreen_config); | ||
| 854 | 902 | ||
| 855 | if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && | 903 | if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && |
| 856 | touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { | 904 | touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { |
| @@ -858,7 +906,7 @@ void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx | |||
| 858 | } | 906 | } |
| 859 | 907 | ||
| 860 | IPC::ResponseBuilder rb{ctx, 6}; | 908 | IPC::ResponseBuilder rb{ctx, 6}; |
| 861 | rb.Push(ResultSuccess); | 909 | rb.Push(result); |
| 862 | rb.PushRaw(touchscreen_config); | 910 | rb.PushRaw(touchscreen_config); |
| 863 | } | 911 | } |
| 864 | 912 | ||
diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h index 4ab4d3931..738313e08 100644 --- a/src/core/hle/service/hid/hid_system_server.h +++ b/src/core/hle/service/hid/hid_system_server.h | |||
| @@ -71,6 +71,9 @@ private: | |||
| 71 | void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); | 71 | void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); |
| 72 | void CheckUsbFirmwareUpdateRequired(HLERequestContext& ctx); | 72 | void CheckUsbFirmwareUpdateRequired(HLERequestContext& ctx); |
| 73 | void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); | 73 | void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); |
| 74 | void SetTouchScreenMagnification(HLERequestContext& ctx); | ||
| 75 | void GetTouchScreenFirmwareVersion(HLERequestContext& ctx); | ||
| 76 | void SetTouchScreenDefaultConfiguration(HLERequestContext& ctx); | ||
| 74 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); | 77 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); |
| 75 | void SetForceHandheldStyleVibration(HLERequestContext& ctx); | 78 | void SetForceHandheldStyleVibration(HLERequestContext& ctx); |
| 76 | void IsUsingCustomButtonConfig(HLERequestContext& ctx); | 79 | void IsUsingCustomButtonConfig(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h index ebc373da5..40230182a 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.h +++ b/src/core/hle/service/set/setting_formats/system_settings.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/vector_math.h" | 12 | #include "common/vector_math.h" |
| 13 | #include "core/hle/service/set/setting_formats/private_settings.h" | 13 | #include "core/hle/service/set/setting_formats/private_settings.h" |
| 14 | #include "core/hle/service/set/settings_types.h" | 14 | #include "core/hle/service/set/settings_types.h" |
| 15 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 15 | 16 | ||
| 16 | namespace Service::Set { | 17 | namespace Service::Set { |
| 17 | 18 | ||
| @@ -257,8 +258,7 @@ struct SystemSettings { | |||
| 257 | std::array<u8, 0x10> analog_stick_user_calibration_left; | 258 | std::array<u8, 0x10> analog_stick_user_calibration_left; |
| 258 | std::array<u8, 0x10> analog_stick_user_calibration_right; | 259 | std::array<u8, 0x10> analog_stick_user_calibration_right; |
| 259 | 260 | ||
| 260 | // nn::settings::system::TouchScreenMode | 261 | TouchScreenMode touch_screen_mode; |
| 261 | s32 touch_screen_mode; | ||
| 262 | INSERT_PADDING_BYTES(0x14); // Reserved | 262 | INSERT_PADDING_BYTES(0x14); // Reserved |
| 263 | 263 | ||
| 264 | TvSettings tv_settings; | 264 | TvSettings tv_settings; |
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index d3d0fb112..7ef4a0ded 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp | |||
| @@ -275,8 +275,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) | |||
| 275 | {184, nullptr, "SetPlatformRegion"}, | 275 | {184, nullptr, "SetPlatformRegion"}, |
| 276 | {185, &ISystemSettingsServer::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"}, | 276 | {185, &ISystemSettingsServer::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"}, |
| 277 | {186, nullptr, "GetMemoryUsageRateFlag"}, | 277 | {186, nullptr, "GetMemoryUsageRateFlag"}, |
| 278 | {187, nullptr, "GetTouchScreenMode"}, | 278 | {187, &ISystemSettingsServer::GetTouchScreenMode, "GetTouchScreenMode"}, |
| 279 | {188, nullptr, "SetTouchScreenMode"}, | 279 | {188, &ISystemSettingsServer::SetTouchScreenMode, "SetTouchScreenMode"}, |
| 280 | {189, nullptr, "GetButtonConfigSettingsFull"}, | 280 | {189, nullptr, "GetButtonConfigSettingsFull"}, |
| 281 | {190, nullptr, "SetButtonConfigSettingsFull"}, | 281 | {190, nullptr, "SetButtonConfigSettingsFull"}, |
| 282 | {191, nullptr, "GetButtonConfigSettingsEmbedded"}, | 282 | {191, nullptr, "GetButtonConfigSettingsEmbedded"}, |
| @@ -1395,6 +1395,28 @@ void ISystemSettingsServer::GetHomeMenuSchemeModel(HLERequestContext& ctx) { | |||
| 1395 | rb.Push(0); | 1395 | rb.Push(0); |
| 1396 | } | 1396 | } |
| 1397 | 1397 | ||
| 1398 | void ISystemSettingsServer::GetTouchScreenMode(HLERequestContext& ctx) { | ||
| 1399 | TouchScreenMode touch_screen_mode{}; | ||
| 1400 | auto res = GetTouchScreenMode(touch_screen_mode); | ||
| 1401 | |||
| 1402 | LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode); | ||
| 1403 | |||
| 1404 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1405 | rb.Push(res); | ||
| 1406 | rb.PushEnum(touch_screen_mode); | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | void ISystemSettingsServer::SetTouchScreenMode(HLERequestContext& ctx) { | ||
| 1410 | IPC::RequestParser rp{ctx}; | ||
| 1411 | const auto touch_screen_mode = rp.PopEnum<TouchScreenMode>(); | ||
| 1412 | auto res = SetTouchScreenMode(touch_screen_mode); | ||
| 1413 | |||
| 1414 | LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode); | ||
| 1415 | |||
| 1416 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1417 | rb.Push(res); | ||
| 1418 | } | ||
| 1419 | |||
| 1398 | void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) { | 1420 | void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) { |
| 1399 | LOG_INFO(Service_SET, "called, field_testing_flag={}", m_system_settings.field_testing_flag); | 1421 | LOG_INFO(Service_SET, "called, field_testing_flag={}", m_system_settings.field_testing_flag); |
| 1400 | 1422 | ||
| @@ -1670,4 +1692,15 @@ Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime( | |||
| 1670 | R_SUCCEED(); | 1692 | R_SUCCEED(); |
| 1671 | } | 1693 | } |
| 1672 | 1694 | ||
| 1695 | Result ISystemSettingsServer::GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const { | ||
| 1696 | touch_screen_mode = m_system_settings.touch_screen_mode; | ||
| 1697 | R_SUCCEED(); | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) { | ||
| 1701 | m_system_settings.touch_screen_mode = touch_screen_mode; | ||
| 1702 | SetSaveNeeded(); | ||
| 1703 | R_SUCCEED(); | ||
| 1704 | } | ||
| 1705 | |||
| 1673 | } // namespace Service::Set | 1706 | } // namespace Service::Set |
diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h index 1982b9723..9a3b36f0c 100644 --- a/src/core/hle/service/set/system_settings_server.h +++ b/src/core/hle/service/set/system_settings_server.h | |||
| @@ -74,6 +74,8 @@ public: | |||
| 74 | Service::PSC::Time::SteadyClockTimePoint& out_time_point) const; | 74 | Service::PSC::Time::SteadyClockTimePoint& out_time_point) const; |
| 75 | Result SetUserSystemClockAutomaticCorrectionUpdatedTime( | 75 | Result SetUserSystemClockAutomaticCorrectionUpdatedTime( |
| 76 | const Service::PSC::Time::SteadyClockTimePoint& time_point); | 76 | const Service::PSC::Time::SteadyClockTimePoint& time_point); |
| 77 | Result GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const; | ||
| 78 | Result SetTouchScreenMode(TouchScreenMode touch_screen_mode); | ||
| 77 | 79 | ||
| 78 | private: | 80 | private: |
| 79 | void SetLanguageCode(HLERequestContext& ctx); | 81 | void SetLanguageCode(HLERequestContext& ctx); |
| @@ -154,6 +156,8 @@ private: | |||
| 154 | void GetChineseTraditionalInputMethod(HLERequestContext& ctx); | 156 | void GetChineseTraditionalInputMethod(HLERequestContext& ctx); |
| 155 | void GetHomeMenuScheme(HLERequestContext& ctx); | 157 | void GetHomeMenuScheme(HLERequestContext& ctx); |
| 156 | void GetHomeMenuSchemeModel(HLERequestContext& ctx); | 158 | void GetHomeMenuSchemeModel(HLERequestContext& ctx); |
| 159 | void GetTouchScreenMode(HLERequestContext& ctx); | ||
| 160 | void SetTouchScreenMode(HLERequestContext& ctx); | ||
| 157 | void GetFieldTestingFlag(HLERequestContext& ctx); | 161 | void GetFieldTestingFlag(HLERequestContext& ctx); |
| 158 | void GetPanelCrcMode(HLERequestContext& ctx); | 162 | void GetPanelCrcMode(HLERequestContext& ctx); |
| 159 | void SetPanelCrcMode(HLERequestContext& ctx); | 163 | void SetPanelCrcMode(HLERequestContext& ctx); |
diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp index 905f35118..d34624d28 100644 --- a/src/frontend_common/config.cpp +++ b/src/frontend_common/config.cpp | |||
| @@ -190,9 +190,9 @@ void Config::ReadTouchscreenValues() { | |||
| 190 | Settings::values.touchscreen.rotation_angle = | 190 | Settings::values.touchscreen.rotation_angle = |
| 191 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0)); | 191 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0)); |
| 192 | Settings::values.touchscreen.diameter_x = | 192 | Settings::values.touchscreen.diameter_x = |
| 193 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 15)); | 193 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 90)); |
| 194 | Settings::values.touchscreen.diameter_y = | 194 | Settings::values.touchscreen.diameter_y = |
| 195 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 15)); | 195 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 90)); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | void Config::ReadAudioValues() { | 198 | void Config::ReadAudioValues() { |
| @@ -478,9 +478,9 @@ void Config::SaveTouchscreenValues() { | |||
| 478 | WriteIntegerSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle, | 478 | WriteIntegerSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle, |
| 479 | std::make_optional(static_cast<u32>(0))); | 479 | std::make_optional(static_cast<u32>(0))); |
| 480 | WriteIntegerSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x, | 480 | WriteIntegerSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x, |
| 481 | std::make_optional(static_cast<u32>(15))); | 481 | std::make_optional(static_cast<u32>(90))); |
| 482 | WriteIntegerSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y, | 482 | WriteIntegerSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y, |
| 483 | std::make_optional(static_cast<u32>(15))); | 483 | std::make_optional(static_cast<u32>(90))); |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | void Config::SaveMotionTouchValues() { | 486 | void Config::SaveMotionTouchValues() { |
diff --git a/src/hid_core/CMakeLists.txt b/src/hid_core/CMakeLists.txt index 64cd6e726..2699e1599 100644 --- a/src/hid_core/CMakeLists.txt +++ b/src/hid_core/CMakeLists.txt | |||
| @@ -99,9 +99,14 @@ add_library(hid_core STATIC | |||
| 99 | resources/system_buttons/system_button_types.h | 99 | resources/system_buttons/system_button_types.h |
| 100 | resources/touch_screen/gesture.cpp | 100 | resources/touch_screen/gesture.cpp |
| 101 | resources/touch_screen/gesture.h | 101 | resources/touch_screen/gesture.h |
| 102 | resources/touch_screen/gesture_types.h | 102 | resources/touch_screen/gesture_handler.cpp |
| 103 | resources/touch_screen/gesture_handler.h | ||
| 103 | resources/touch_screen/touch_screen.cpp | 104 | resources/touch_screen/touch_screen.cpp |
| 104 | resources/touch_screen/touch_screen.h | 105 | resources/touch_screen/touch_screen.h |
| 106 | resources/touch_screen/touch_screen_driver.cpp | ||
| 107 | resources/touch_screen/touch_screen_driver.h | ||
| 108 | resources/touch_screen/touch_screen_resource.cpp | ||
| 109 | resources/touch_screen/touch_screen_resource.h | ||
| 105 | resources/touch_screen/touch_types.h | 110 | resources/touch_screen/touch_types.h |
| 106 | resources/unique_pad/unique_pad.cpp | 111 | resources/unique_pad/unique_pad.cpp |
| 107 | resources/unique_pad/unique_pad.h | 112 | resources/unique_pad/unique_pad.h |
diff --git a/src/hid_core/hid_result.h b/src/hid_core/hid_result.h index df9b28c9a..c8dd07bfe 100644 --- a/src/hid_core/hid_result.h +++ b/src/hid_core/hid_result.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | namespace Service::HID { | 8 | namespace Service::HID { |
| 9 | 9 | ||
| 10 | constexpr Result PalmaResultSuccess{ErrorModule::HID, 0}; | 10 | constexpr Result PalmaResultSuccess{ErrorModule::HID, 0}; |
| 11 | |||
| 12 | constexpr Result ResultTouchNotInitialized{ErrorModule::HID, 41}; | ||
| 13 | constexpr Result ResultTouchOverflow{ErrorModule::HID, 42}; | ||
| 14 | |||
| 11 | constexpr Result NpadInvalidHandle{ErrorModule::HID, 100}; | 15 | constexpr Result NpadInvalidHandle{ErrorModule::HID, 100}; |
| 12 | constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; | 16 | constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; |
| 13 | 17 | ||
| @@ -23,6 +27,10 @@ constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423}; | |||
| 23 | constexpr Result ResultNfcIsNotReady{ErrorModule::HID, 461}; | 27 | constexpr Result ResultNfcIsNotReady{ErrorModule::HID, 461}; |
| 24 | constexpr Result ResultNfcXcdHandleIsNotInitialized{ErrorModule::HID, 464}; | 28 | constexpr Result ResultNfcXcdHandleIsNotInitialized{ErrorModule::HID, 464}; |
| 25 | constexpr Result ResultIrSensorIsNotReady{ErrorModule::HID, 501}; | 29 | constexpr Result ResultIrSensorIsNotReady{ErrorModule::HID, 501}; |
| 30 | |||
| 31 | constexpr Result ResultGestureOverflow{ErrorModule::HID, 522}; | ||
| 32 | constexpr Result ResultGestureNotInitialized{ErrorModule::HID, 523}; | ||
| 33 | |||
| 26 | constexpr Result ResultMcuIsNotReady{ErrorModule::HID, 541}; | 34 | constexpr Result ResultMcuIsNotReady{ErrorModule::HID, 541}; |
| 27 | 35 | ||
| 28 | constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; | 36 | constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; |
diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index ffb5f1926..1b2fc6295 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h | |||
| @@ -299,12 +299,6 @@ enum class GyroscopeZeroDriftMode : u32 { | |||
| 299 | Tight = 2, | 299 | Tight = 2, |
| 300 | }; | 300 | }; |
| 301 | 301 | ||
| 302 | // This is nn::settings::system::TouchScreenMode | ||
| 303 | enum class TouchScreenMode : u32 { | ||
| 304 | Stylus = 0, | ||
| 305 | Standard = 1, | ||
| 306 | }; | ||
| 307 | |||
| 308 | // This is nn::hid::TouchScreenModeForNx | 302 | // This is nn::hid::TouchScreenModeForNx |
| 309 | enum class TouchScreenModeForNx : u8 { | 303 | enum class TouchScreenModeForNx : u8 { |
| 310 | UseSystemSetting, | 304 | UseSystemSetting, |
| @@ -354,18 +348,6 @@ struct TouchAttribute { | |||
| 354 | }; | 348 | }; |
| 355 | static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"); | 349 | static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"); |
| 356 | 350 | ||
| 357 | // This is nn::hid::TouchState | ||
| 358 | struct TouchState { | ||
| 359 | u64 delta_time{}; | ||
| 360 | TouchAttribute attribute{}; | ||
| 361 | u32 finger{}; | ||
| 362 | Common::Point<u32> position{}; | ||
| 363 | u32 diameter_x{}; | ||
| 364 | u32 diameter_y{}; | ||
| 365 | u32 rotation_angle{}; | ||
| 366 | }; | ||
| 367 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); | ||
| 368 | |||
| 369 | struct TouchFinger { | 351 | struct TouchFinger { |
| 370 | u64 last_touch{}; | 352 | u64 last_touch{}; |
| 371 | Common::Point<float> position{}; | 353 | Common::Point<float> position{}; |
| @@ -756,4 +738,14 @@ struct UniquePadId { | |||
| 756 | }; | 738 | }; |
| 757 | static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); | 739 | static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); |
| 758 | 740 | ||
| 741 | // This is nn::hid::system::FirmwareVersion | ||
| 742 | struct FirmwareVersion { | ||
| 743 | u8 major; | ||
| 744 | u8 minor; | ||
| 745 | u8 micro; | ||
| 746 | u8 revision; | ||
| 747 | std::array<char, 0xc> device_identifier; | ||
| 748 | }; | ||
| 749 | static_assert(sizeof(FirmwareVersion) == 0x10, "FirmwareVersion is an invalid size"); | ||
| 750 | |||
| 759 | } // namespace Core::HID | 751 | } // namespace Core::HID |
diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index e78665d31..68ce2c7ae 100644 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "hid_core/resources/applet_resource.h" | 15 | #include "hid_core/resources/applet_resource.h" |
| 16 | #include "hid_core/resources/debug_pad/debug_pad.h" | 16 | #include "hid_core/resources/debug_pad/debug_pad.h" |
| 17 | #include "hid_core/resources/digitizer/digitizer.h" | 17 | #include "hid_core/resources/digitizer/digitizer.h" |
| 18 | #include "hid_core/resources/hid_firmware_settings.h" | ||
| 18 | #include "hid_core/resources/keyboard/keyboard.h" | 19 | #include "hid_core/resources/keyboard/keyboard.h" |
| 19 | #include "hid_core/resources/mouse/debug_mouse.h" | 20 | #include "hid_core/resources/mouse/debug_mouse.h" |
| 20 | #include "hid_core/resources/mouse/mouse.h" | 21 | #include "hid_core/resources/mouse/mouse.h" |
| @@ -29,6 +30,8 @@ | |||
| 29 | #include "hid_core/resources/system_buttons/sleep_button.h" | 30 | #include "hid_core/resources/system_buttons/sleep_button.h" |
| 30 | #include "hid_core/resources/touch_screen/gesture.h" | 31 | #include "hid_core/resources/touch_screen/gesture.h" |
| 31 | #include "hid_core/resources/touch_screen/touch_screen.h" | 32 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 33 | #include "hid_core/resources/touch_screen/touch_screen_driver.h" | ||
| 34 | #include "hid_core/resources/touch_screen/touch_screen_resource.h" | ||
| 32 | #include "hid_core/resources/unique_pad/unique_pad.h" | 35 | #include "hid_core/resources/unique_pad/unique_pad.h" |
| 33 | #include "hid_core/resources/vibration/gc_vibration_device.h" | 36 | #include "hid_core/resources/vibration/gc_vibration_device.h" |
| 34 | #include "hid_core/resources/vibration/n64_vibration_device.h" | 37 | #include "hid_core/resources/vibration/n64_vibration_device.h" |
| @@ -45,12 +48,16 @@ constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // | |||
| 45 | constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) | 48 | constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) |
| 46 | constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) | 49 | constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) |
| 47 | 50 | ||
| 48 | ResourceManager::ResourceManager(Core::System& system_) | 51 | ResourceManager::ResourceManager(Core::System& system_, |
| 49 | : system{system_}, service_context{system_, "hid"} { | 52 | std::shared_ptr<HidFirmwareSettings> settings) |
| 53 | : firmware_settings{settings}, system{system_}, service_context{system_, "hid"} { | ||
| 50 | applet_resource = std::make_shared<AppletResource>(system); | 54 | applet_resource = std::make_shared<AppletResource>(system); |
| 51 | } | 55 | } |
| 52 | 56 | ||
| 53 | ResourceManager::~ResourceManager() = default; | 57 | ResourceManager::~ResourceManager() { |
| 58 | system.CoreTiming().UnscheduleEvent(touch_update_event); | ||
| 59 | input_event->Finalize(); | ||
| 60 | }; | ||
| 54 | 61 | ||
| 55 | void ResourceManager::Initialize() { | 62 | void ResourceManager::Initialize() { |
| 56 | if (is_initialized) { | 63 | if (is_initialized) { |
| @@ -59,7 +66,9 @@ void ResourceManager::Initialize() { | |||
| 59 | 66 | ||
| 60 | system.HIDCore().ReloadInputDevices(); | 67 | system.HIDCore().ReloadInputDevices(); |
| 61 | 68 | ||
| 62 | handheld_config = std::make_shared<HandheldConfig>(); | 69 | input_event = service_context.CreateEvent("ResourceManager:InputEvent"); |
| 70 | |||
| 71 | InitializeHandheldConfig(); | ||
| 63 | InitializeHidCommonSampler(); | 72 | InitializeHidCommonSampler(); |
| 64 | InitializeTouchScreenSampler(); | 73 | InitializeTouchScreenSampler(); |
| 65 | InitializeConsoleSixAxisSampler(); | 74 | InitializeConsoleSixAxisSampler(); |
| @@ -154,6 +163,7 @@ Result ResourceManager::CreateAppletResource(u64 aruid) { | |||
| 154 | npad->Activate(); | 163 | npad->Activate(); |
| 155 | six_axis->Activate(); | 164 | six_axis->Activate(); |
| 156 | touch_screen->Activate(); | 165 | touch_screen->Activate(); |
| 166 | gesture->Activate(); | ||
| 157 | 167 | ||
| 158 | return GetNpad()->ActivateNpadResource(aruid); | 168 | return GetNpad()->ActivateNpadResource(aruid); |
| 159 | } | 169 | } |
| @@ -163,6 +173,17 @@ Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { | |||
| 163 | return applet_resource->CreateAppletResource(aruid); | 173 | return applet_resource->CreateAppletResource(aruid); |
| 164 | } | 174 | } |
| 165 | 175 | ||
| 176 | void ResourceManager::InitializeHandheldConfig() { | ||
| 177 | handheld_config = std::make_shared<HandheldConfig>(); | ||
| 178 | handheld_config->is_handheld_hid_enabled = true; | ||
| 179 | handheld_config->is_joycon_rail_enabled = true; | ||
| 180 | handheld_config->is_force_handheld_style_vibration = false; | ||
| 181 | handheld_config->is_force_handheld = false; | ||
| 182 | if (firmware_settings->IsHandheldForced()) { | ||
| 183 | handheld_config->is_joycon_rail_enabled = false; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 166 | void ResourceManager::InitializeHidCommonSampler() { | 187 | void ResourceManager::InitializeHidCommonSampler() { |
| 167 | debug_pad = std::make_shared<DebugPad>(system.HIDCore()); | 188 | debug_pad = std::make_shared<DebugPad>(system.HIDCore()); |
| 168 | mouse = std::make_shared<Mouse>(system.HIDCore()); | 189 | mouse = std::make_shared<Mouse>(system.HIDCore()); |
| @@ -170,7 +191,6 @@ void ResourceManager::InitializeHidCommonSampler() { | |||
| 170 | keyboard = std::make_shared<Keyboard>(system.HIDCore()); | 191 | keyboard = std::make_shared<Keyboard>(system.HIDCore()); |
| 171 | unique_pad = std::make_shared<UniquePad>(system.HIDCore()); | 192 | unique_pad = std::make_shared<UniquePad>(system.HIDCore()); |
| 172 | npad = std::make_shared<NPad>(system.HIDCore(), service_context); | 193 | npad = std::make_shared<NPad>(system.HIDCore(), service_context); |
| 173 | gesture = std::make_shared<Gesture>(system.HIDCore()); | ||
| 174 | home_button = std::make_shared<HomeButton>(system.HIDCore()); | 194 | home_button = std::make_shared<HomeButton>(system.HIDCore()); |
| 175 | sleep_button = std::make_shared<SleepButton>(system.HIDCore()); | 195 | sleep_button = std::make_shared<SleepButton>(system.HIDCore()); |
| 176 | capture_button = std::make_shared<CaptureButton>(system.HIDCore()); | 196 | capture_button = std::make_shared<CaptureButton>(system.HIDCore()); |
| @@ -185,7 +205,8 @@ void ResourceManager::InitializeHidCommonSampler() { | |||
| 185 | 205 | ||
| 186 | const auto settings = | 206 | const auto settings = |
| 187 | system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); | 207 | system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); |
| 188 | npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings); | 208 | npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, input_event, |
| 209 | &input_mutex, settings); | ||
| 189 | 210 | ||
| 190 | six_axis->SetAppletResource(applet_resource, &shared_mutex); | 211 | six_axis->SetAppletResource(applet_resource, &shared_mutex); |
| 191 | mouse->SetAppletResource(applet_resource, &shared_mutex); | 212 | mouse->SetAppletResource(applet_resource, &shared_mutex); |
| @@ -196,11 +217,25 @@ void ResourceManager::InitializeHidCommonSampler() { | |||
| 196 | } | 217 | } |
| 197 | 218 | ||
| 198 | void ResourceManager::InitializeTouchScreenSampler() { | 219 | void ResourceManager::InitializeTouchScreenSampler() { |
| 199 | gesture = std::make_shared<Gesture>(system.HIDCore()); | 220 | // This is nn.hid.TouchScreenSampler |
| 200 | touch_screen = std::make_shared<TouchScreen>(system.HIDCore()); | 221 | touch_resource = std::make_shared<TouchResource>(system); |
| 222 | touch_driver = std::make_shared<TouchDriver>(system.HIDCore()); | ||
| 223 | touch_screen = std::make_shared<TouchScreen>(touch_resource); | ||
| 224 | gesture = std::make_shared<Gesture>(touch_resource); | ||
| 225 | |||
| 226 | touch_update_event = Core::Timing::CreateEvent( | ||
| 227 | "HID::TouchUpdateCallback", | ||
| 228 | [this](s64 time, | ||
| 229 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 230 | touch_resource->OnTouchUpdate(time); | ||
| 231 | return std::nullopt; | ||
| 232 | }); | ||
| 201 | 233 | ||
| 202 | touch_screen->SetAppletResource(applet_resource, &shared_mutex); | 234 | touch_resource->SetTouchDriver(touch_driver); |
| 203 | gesture->SetAppletResource(applet_resource, &shared_mutex); | 235 | touch_resource->SetAppletResource(applet_resource, &shared_mutex); |
| 236 | touch_resource->SetInputEvent(input_event, &input_mutex); | ||
| 237 | touch_resource->SetHandheldConfig(handheld_config); | ||
| 238 | touch_resource->SetTimerEvent(touch_update_event); | ||
| 204 | } | 239 | } |
| 205 | 240 | ||
| 206 | void ResourceManager::InitializeConsoleSixAxisSampler() { | 241 | void ResourceManager::InitializeConsoleSixAxisSampler() { |
| @@ -388,13 +423,15 @@ Result ResourceManager::SendVibrationValue(u64 aruid, | |||
| 388 | return result; | 423 | return result; |
| 389 | } | 424 | } |
| 390 | 425 | ||
| 426 | Result ResourceManager::GetTouchScreenFirmwareVersion(Core::HID::FirmwareVersion& firmware) const { | ||
| 427 | return ResultSuccess; | ||
| 428 | } | ||
| 429 | |||
| 391 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { | 430 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { |
| 392 | auto& core_timing = system.CoreTiming(); | 431 | auto& core_timing = system.CoreTiming(); |
| 393 | debug_pad->OnUpdate(core_timing); | 432 | debug_pad->OnUpdate(core_timing); |
| 394 | digitizer->OnUpdate(core_timing); | 433 | digitizer->OnUpdate(core_timing); |
| 395 | unique_pad->OnUpdate(core_timing); | 434 | unique_pad->OnUpdate(core_timing); |
| 396 | gesture->OnUpdate(core_timing); | ||
| 397 | touch_screen->OnUpdate(core_timing); | ||
| 398 | palma->OnUpdate(core_timing); | 435 | palma->OnUpdate(core_timing); |
| 399 | home_button->OnUpdate(core_timing); | 436 | home_button->OnUpdate(core_timing); |
| 400 | sleep_button->OnUpdate(core_timing); | 437 | sleep_button->OnUpdate(core_timing); |
diff --git a/src/hid_core/resource_manager.h b/src/hid_core/resource_manager.h index 128e00125..0bfe09511 100644 --- a/src/hid_core/resource_manager.h +++ b/src/hid_core/resource_manager.h | |||
| @@ -11,6 +11,7 @@ class System; | |||
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Core::HID { | 13 | namespace Core::HID { |
| 14 | struct FirmwareVersion; | ||
| 14 | struct VibrationDeviceHandle; | 15 | struct VibrationDeviceHandle; |
| 15 | struct VibrationValue; | 16 | struct VibrationValue; |
| 16 | struct VibrationDeviceInfo; | 17 | struct VibrationDeviceInfo; |
| @@ -21,8 +22,9 @@ struct EventType; | |||
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | namespace Kernel { | 24 | namespace Kernel { |
| 25 | class KEvent; | ||
| 24 | class KSharedMemory; | 26 | class KSharedMemory; |
| 25 | } | 27 | } // namespace Kernel |
| 26 | 28 | ||
| 27 | namespace Service::HID { | 29 | namespace Service::HID { |
| 28 | class AppletResource; | 30 | class AppletResource; |
| @@ -33,6 +35,7 @@ class DebugMouse; | |||
| 33 | class DebugPad; | 35 | class DebugPad; |
| 34 | class Digitizer; | 36 | class Digitizer; |
| 35 | class Gesture; | 37 | class Gesture; |
| 38 | class HidFirmwareSettings; | ||
| 36 | class HomeButton; | 39 | class HomeButton; |
| 37 | class Keyboard; | 40 | class Keyboard; |
| 38 | class Mouse; | 41 | class Mouse; |
| @@ -42,6 +45,8 @@ class SevenSixAxis; | |||
| 42 | class SixAxis; | 45 | class SixAxis; |
| 43 | class SleepButton; | 46 | class SleepButton; |
| 44 | class TouchScreen; | 47 | class TouchScreen; |
| 48 | class TouchDriver; | ||
| 49 | class TouchResource; | ||
| 45 | class UniquePad; | 50 | class UniquePad; |
| 46 | class NpadVibrationBase; | 51 | class NpadVibrationBase; |
| 47 | class NpadN64VibrationDevice; | 52 | class NpadN64VibrationDevice; |
| @@ -52,7 +57,7 @@ struct HandheldConfig; | |||
| 52 | class ResourceManager { | 57 | class ResourceManager { |
| 53 | 58 | ||
| 54 | public: | 59 | public: |
| 55 | explicit ResourceManager(Core::System& system_); | 60 | explicit ResourceManager(Core::System& system_, std::shared_ptr<HidFirmwareSettings> settings); |
| 56 | ~ResourceManager(); | 61 | ~ResourceManager(); |
| 57 | 62 | ||
| 58 | void Initialize(); | 63 | void Initialize(); |
| @@ -102,6 +107,8 @@ public: | |||
| 102 | Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle, | 107 | Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle, |
| 103 | const Core::HID::VibrationValue& value); | 108 | const Core::HID::VibrationValue& value); |
| 104 | 109 | ||
| 110 | Result GetTouchScreenFirmwareVersion(Core::HID::FirmwareVersion& firmware) const; | ||
| 111 | |||
| 105 | void UpdateControllers(std::chrono::nanoseconds ns_late); | 112 | void UpdateControllers(std::chrono::nanoseconds ns_late); |
| 106 | void UpdateNpad(std::chrono::nanoseconds ns_late); | 113 | void UpdateNpad(std::chrono::nanoseconds ns_late); |
| 107 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); | 114 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); |
| @@ -109,6 +116,7 @@ public: | |||
| 109 | 116 | ||
| 110 | private: | 117 | private: |
| 111 | Result CreateAppletResourceImpl(u64 aruid); | 118 | Result CreateAppletResourceImpl(u64 aruid); |
| 119 | void InitializeHandheldConfig(); | ||
| 112 | void InitializeHidCommonSampler(); | 120 | void InitializeHidCommonSampler(); |
| 113 | void InitializeTouchScreenSampler(); | 121 | void InitializeTouchScreenSampler(); |
| 114 | void InitializeConsoleSixAxisSampler(); | 122 | void InitializeConsoleSixAxisSampler(); |
| @@ -117,37 +125,46 @@ private: | |||
| 117 | bool is_initialized{false}; | 125 | bool is_initialized{false}; |
| 118 | 126 | ||
| 119 | mutable std::recursive_mutex shared_mutex; | 127 | mutable std::recursive_mutex shared_mutex; |
| 120 | std::shared_ptr<AppletResource> applet_resource = nullptr; | 128 | std::shared_ptr<AppletResource> applet_resource{nullptr}; |
| 121 | 129 | ||
| 122 | std::shared_ptr<CaptureButton> capture_button = nullptr; | 130 | mutable std::mutex input_mutex; |
| 123 | std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr; | 131 | Kernel::KEvent* input_event{nullptr}; |
| 124 | std::shared_ptr<DebugMouse> debug_mouse = nullptr; | 132 | |
| 125 | std::shared_ptr<DebugPad> debug_pad = nullptr; | 133 | std::shared_ptr<HandheldConfig> handheld_config{nullptr}; |
| 126 | std::shared_ptr<Digitizer> digitizer = nullptr; | 134 | std::shared_ptr<HidFirmwareSettings> firmware_settings{nullptr}; |
| 127 | std::shared_ptr<Gesture> gesture = nullptr; | 135 | |
| 128 | std::shared_ptr<HomeButton> home_button = nullptr; | 136 | std::shared_ptr<CaptureButton> capture_button{nullptr}; |
| 129 | std::shared_ptr<Keyboard> keyboard = nullptr; | 137 | std::shared_ptr<ConsoleSixAxis> console_six_axis{nullptr}; |
| 130 | std::shared_ptr<Mouse> mouse = nullptr; | 138 | std::shared_ptr<DebugMouse> debug_mouse{nullptr}; |
| 131 | std::shared_ptr<NPad> npad = nullptr; | 139 | std::shared_ptr<DebugPad> debug_pad{nullptr}; |
| 132 | std::shared_ptr<Palma> palma = nullptr; | 140 | std::shared_ptr<Digitizer> digitizer{nullptr}; |
| 133 | std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr; | 141 | std::shared_ptr<HomeButton> home_button{nullptr}; |
| 134 | std::shared_ptr<SixAxis> six_axis = nullptr; | 142 | std::shared_ptr<Keyboard> keyboard{nullptr}; |
| 135 | std::shared_ptr<SleepButton> sleep_button = nullptr; | 143 | std::shared_ptr<Mouse> mouse{nullptr}; |
| 136 | std::shared_ptr<TouchScreen> touch_screen = nullptr; | 144 | std::shared_ptr<NPad> npad{nullptr}; |
| 137 | std::shared_ptr<UniquePad> unique_pad = nullptr; | 145 | std::shared_ptr<Palma> palma{nullptr}; |
| 138 | 146 | std::shared_ptr<SevenSixAxis> seven_six_axis{nullptr}; | |
| 139 | std::shared_ptr<HandheldConfig> handheld_config = nullptr; | 147 | std::shared_ptr<SixAxis> six_axis{nullptr}; |
| 148 | std::shared_ptr<SleepButton> sleep_button{nullptr}; | ||
| 149 | std::shared_ptr<UniquePad> unique_pad{nullptr}; | ||
| 140 | 150 | ||
| 141 | // TODO: Create these resources | 151 | // TODO: Create these resources |
| 142 | // std::shared_ptr<AudioControl> audio_control = nullptr; | 152 | // std::shared_ptr<AudioControl> audio_control{nullptr}; |
| 143 | // std::shared_ptr<ButtonConfig> button_config = nullptr; | 153 | // std::shared_ptr<ButtonConfig> button_config{nullptr}; |
| 144 | // std::shared_ptr<Config> config = nullptr; | 154 | // std::shared_ptr<Config> config{nullptr}; |
| 145 | // std::shared_ptr<Connection> connection = nullptr; | 155 | // std::shared_ptr<Connection> connection{nullptr}; |
| 146 | // std::shared_ptr<CustomConfig> custom_config = nullptr; | 156 | // std::shared_ptr<CustomConfig> custom_config{nullptr}; |
| 147 | // std::shared_ptr<Digitizer> digitizer = nullptr; | 157 | // std::shared_ptr<Digitizer> digitizer{nullptr}; |
| 148 | // std::shared_ptr<Hdls> hdls = nullptr; | 158 | // std::shared_ptr<Hdls> hdls{nullptr}; |
| 149 | // std::shared_ptr<PlayReport> play_report = nullptr; | 159 | // std::shared_ptr<PlayReport> play_report{nullptr}; |
| 150 | // std::shared_ptr<Rail> rail = nullptr; | 160 | // std::shared_ptr<Rail> rail{nullptr}; |
| 161 | |||
| 162 | // Touch Resources | ||
| 163 | std::shared_ptr<Gesture> gesture{nullptr}; | ||
| 164 | std::shared_ptr<TouchScreen> touch_screen{nullptr}; | ||
| 165 | std::shared_ptr<TouchResource> touch_resource{nullptr}; | ||
| 166 | std::shared_ptr<TouchDriver> touch_driver{nullptr}; | ||
| 167 | std::shared_ptr<Core::Timing::EventType> touch_update_event{nullptr}; | ||
| 151 | 168 | ||
| 152 | Core::System& system; | 169 | Core::System& system; |
| 153 | KernelHelpers::ServiceContext service_context; | 170 | KernelHelpers::ServiceContext service_context; |
| @@ -162,12 +179,12 @@ public: | |||
| 162 | private: | 179 | private: |
| 163 | void GetSharedMemoryHandle(HLERequestContext& ctx); | 180 | void GetSharedMemoryHandle(HLERequestContext& ctx); |
| 164 | 181 | ||
| 165 | std::shared_ptr<Core::Timing::EventType> npad_update_event; | 182 | std::shared_ptr<Core::Timing::EventType> npad_update_event{nullptr}; |
| 166 | std::shared_ptr<Core::Timing::EventType> default_update_event; | 183 | std::shared_ptr<Core::Timing::EventType> default_update_event{nullptr}; |
| 167 | std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; | 184 | std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event{nullptr}; |
| 168 | std::shared_ptr<Core::Timing::EventType> motion_update_event; | 185 | std::shared_ptr<Core::Timing::EventType> motion_update_event{nullptr}; |
| 169 | 186 | ||
| 170 | u64 aruid; | 187 | u64 aruid{}; |
| 171 | std::shared_ptr<ResourceManager> resource_manager; | 188 | std::shared_ptr<ResourceManager> resource_manager; |
| 172 | }; | 189 | }; |
| 173 | 190 | ||
diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index db4134037..243beb1c7 100644 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp | |||
| @@ -118,6 +118,12 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { | |||
| 118 | data[index].aruid = 0; | 118 | data[index].aruid = 0; |
| 119 | 119 | ||
| 120 | registration_list.flag[index] = RegistrationStatus::PendingDelete; | 120 | registration_list.flag[index] = RegistrationStatus::PendingDelete; |
| 121 | |||
| 122 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 123 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 124 | active_aruid = registration_list.aruid[i]; | ||
| 125 | } | ||
| 126 | } | ||
| 121 | } | 127 | } |
| 122 | 128 | ||
| 123 | void AppletResource::FreeAppletResourceId(u64 aruid) { | 129 | void AppletResource::FreeAppletResourceId(u64 aruid) { |
diff --git a/src/hid_core/resources/applet_resource.h b/src/hid_core/resources/applet_resource.h index e9710d306..4a5416fb2 100644 --- a/src/hid_core/resources/applet_resource.h +++ b/src/hid_core/resources/applet_resource.h | |||
| @@ -13,11 +13,12 @@ | |||
| 13 | 13 | ||
| 14 | namespace Core { | 14 | namespace Core { |
| 15 | class System; | 15 | class System; |
| 16 | } | 16 | } // namespace Core |
| 17 | 17 | ||
| 18 | namespace Kernel { | 18 | namespace Kernel { |
| 19 | class KEvent; | ||
| 19 | class KSharedMemory; | 20 | class KSharedMemory; |
| 20 | } | 21 | } // namespace Kernel |
| 21 | 22 | ||
| 22 | namespace Service::HID { | 23 | namespace Service::HID { |
| 23 | struct SharedMemoryFormat; | 24 | struct SharedMemoryFormat; |
| @@ -73,7 +74,8 @@ struct AppletResourceHolder { | |||
| 73 | std::recursive_mutex* shared_mutex{nullptr}; | 74 | std::recursive_mutex* shared_mutex{nullptr}; |
| 74 | NPadResource* shared_npad_resource{nullptr}; | 75 | NPadResource* shared_npad_resource{nullptr}; |
| 75 | std::shared_ptr<HandheldConfig> handheld_config{nullptr}; | 76 | std::shared_ptr<HandheldConfig> handheld_config{nullptr}; |
| 76 | long* handle_1; | 77 | Kernel::KEvent* input_event{nullptr}; |
| 78 | std::mutex* input_mutex{nullptr}; | ||
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 79 | class AppletResource { | 81 | class AppletResource { |
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 2823be348..1a58eff4a 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp | |||
| @@ -1070,11 +1070,14 @@ void NPad::UnregisterAppletResourceUserId(u64 aruid) { | |||
| 1070 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, | 1070 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, |
| 1071 | std::recursive_mutex* shared_mutex, | 1071 | std::recursive_mutex* shared_mutex, |
| 1072 | std::shared_ptr<HandheldConfig> handheld_config, | 1072 | std::shared_ptr<HandheldConfig> handheld_config, |
| 1073 | Kernel::KEvent* input_event, std::mutex* input_mutex, | ||
| 1073 | std::shared_ptr<Service::Set::ISystemSettingsServer> settings) { | 1074 | std::shared_ptr<Service::Set::ISystemSettingsServer> settings) { |
| 1074 | applet_resource_holder.applet_resource = resource; | 1075 | applet_resource_holder.applet_resource = resource; |
| 1075 | applet_resource_holder.shared_mutex = shared_mutex; | 1076 | applet_resource_holder.shared_mutex = shared_mutex; |
| 1076 | applet_resource_holder.shared_npad_resource = &npad_resource; | 1077 | applet_resource_holder.shared_npad_resource = &npad_resource; |
| 1077 | applet_resource_holder.handheld_config = handheld_config; | 1078 | applet_resource_holder.handheld_config = handheld_config; |
| 1079 | applet_resource_holder.input_event = input_event; | ||
| 1080 | applet_resource_holder.input_mutex = input_mutex; | ||
| 1078 | 1081 | ||
| 1079 | vibration_handler.SetSettingsService(settings); | 1082 | vibration_handler.SetSettingsService(settings); |
| 1080 | 1083 | ||
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 3b1a69e7f..4e26ed2e8 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h | |||
| @@ -131,6 +131,7 @@ public: | |||
| 131 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, | 131 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, |
| 132 | std::recursive_mutex* shared_mutex, | 132 | std::recursive_mutex* shared_mutex, |
| 133 | std::shared_ptr<HandheldConfig> handheld_config, | 133 | std::shared_ptr<HandheldConfig> handheld_config, |
| 134 | Kernel::KEvent* input_event, std::mutex* input_mutex, | ||
| 134 | std::shared_ptr<Service::Set::ISystemSettingsServer> settings); | 135 | std::shared_ptr<Service::Set::ISystemSettingsServer> settings); |
| 135 | 136 | ||
| 136 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); | 137 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); |
| @@ -204,9 +205,6 @@ private: | |||
| 204 | std::array<AbstractPad, MaxSupportedNpadIdTypes> abstracted_pads; | 205 | std::array<AbstractPad, MaxSupportedNpadIdTypes> abstracted_pads; |
| 205 | NpadVibration vibration_handler{}; | 206 | NpadVibration vibration_handler{}; |
| 206 | 207 | ||
| 207 | Kernel::KEvent* input_event{nullptr}; | ||
| 208 | std::mutex* input_mutex{nullptr}; | ||
| 209 | |||
| 210 | std::atomic<u64> press_state{}; | 208 | std::atomic<u64> press_state{}; |
| 211 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> | 209 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> |
| 212 | controller_data{}; | 210 | controller_data{}; |
diff --git a/src/hid_core/resources/npad/npad_resource.cpp b/src/hid_core/resources/npad/npad_resource.cpp index ea9fc14ed..8dd86b58e 100644 --- a/src/hid_core/resources/npad/npad_resource.cpp +++ b/src/hid_core/resources/npad/npad_resource.cpp | |||
| @@ -72,6 +72,12 @@ void NPadResource::UnregisterAppletResourceUserId(u64 aruid) { | |||
| 72 | state[aruid_index] = {}; | 72 | state[aruid_index] = {}; |
| 73 | registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete; | 73 | registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete; |
| 74 | } | 74 | } |
| 75 | |||
| 76 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 77 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 78 | active_data_aruid = registration_list.aruid[i]; | ||
| 79 | } | ||
| 80 | } | ||
| 75 | } | 81 | } |
| 76 | 82 | ||
| 77 | void NPadResource::DestroyStyleSetUpdateEvents(u64 aruid) { | 83 | void NPadResource::DestroyStyleSetUpdateEvents(u64 aruid) { |
diff --git a/src/hid_core/resources/touch_screen/gesture.cpp b/src/hid_core/resources/touch_screen/gesture.cpp index 0ecc0941f..eaa0cc7d0 100644 --- a/src/hid_core/resources/touch_screen/gesture.cpp +++ b/src/hid_core/resources/touch_screen/gesture.cpp | |||
| @@ -1,366 +1,53 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/math_util.h" | ||
| 5 | #include "common/settings.h" | ||
| 6 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "hid_core/frontend/emulated_console.h" | ||
| 8 | #include "hid_core/hid_core.h" | ||
| 9 | #include "hid_core/resources/applet_resource.h" | ||
| 10 | #include "hid_core/resources/shared_memory_format.h" | ||
| 11 | #include "hid_core/resources/touch_screen/gesture.h" | 4 | #include "hid_core/resources/touch_screen/gesture.h" |
| 5 | #include "hid_core/resources/touch_screen/touch_screen_resource.h" | ||
| 12 | 6 | ||
| 13 | namespace Service::HID { | 7 | 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 | 8 | ||
| 21 | constexpr f32 Square(s32 num) { | 9 | Gesture::Gesture(std::shared_ptr<TouchResource> resource) : touch_resource{resource} {} |
| 22 | return static_cast<f32>(num * num); | ||
| 23 | } | ||
| 24 | 10 | ||
| 25 | Gesture::Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { | ||
| 26 | console = hid_core.GetEmulatedConsole(); | ||
| 27 | } | ||
| 28 | Gesture::~Gesture() = default; | 11 | Gesture::~Gesture() = default; |
| 29 | 12 | ||
| 30 | void Gesture::OnInit() { | 13 | Result Gesture::Activate() { |
| 31 | std::scoped_lock shared_lock{*shared_mutex}; | 14 | std::scoped_lock lock{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 | 15 | ||
| 170 | // Promote to pan type if touch moved | 16 | // TODO: Result result = CreateThread(); |
| 171 | for (size_t id = 0; id < MAX_POINTS; id++) { | 17 | Result result = ResultSuccess; |
| 172 | if (gesture.points[id] != last_gesture.points[id]) { | 18 | if (result.IsError()) { |
| 173 | type = GestureType::Pan; | 19 | return result; |
| 174 | break; | ||
| 175 | } | ||
| 176 | } | 20 | } |
| 177 | 21 | ||
| 178 | // Number of fingers changed cancel the last event and clear data | 22 | result = touch_resource->ActivateGesture(); |
| 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 | 23 | ||
| 194 | // Promote to press type | 24 | if (result.IsError()) { |
| 195 | if (last_entry.type == GestureType::Touch) { | 25 | // TODO: StopThread(); |
| 196 | type = GestureType::Press; | ||
| 197 | } | 26 | } |
| 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 | 27 | ||
| 204 | if (last_gesture_props.active_points != 0) { | 28 | return result; |
| 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 | } | 29 | } |
| 234 | 30 | ||
| 235 | void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | 31 | Result Gesture::Activate(u64 aruid, u32 basic_gesture_id) { |
| 236 | GestureType& type, GestureAttribute& attributes) { | 32 | std::scoped_lock lock{mutex}; |
| 237 | type = GestureType::Tap; | 33 | return touch_resource->ActivateGesture(aruid, basic_gesture_id); |
| 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 | } | 34 | } |
| 247 | 35 | ||
| 248 | void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | 36 | Result Gesture::Deactivate() { |
| 249 | GestureType& type, f32 time_difference) { | 37 | std::scoped_lock lock{mutex}; |
| 250 | const auto& last_entry = GetLastGestureEntry(); | 38 | const auto result = touch_resource->DeactivateGesture(); |
| 251 | 39 | ||
| 252 | next_state.delta = gesture.mid_point - last_entry.pos; | 40 | if (result.IsError()) { |
| 253 | next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference; | 41 | return result; |
| 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 | } | 42 | } |
| 263 | 43 | ||
| 264 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / | 44 | // TODO: return StopThread(); |
| 265 | (1 + (gesture.angle * last_gesture_props.angle))); | 45 | return ResultSuccess; |
| 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 | } | 46 | } |
| 273 | 47 | ||
| 274 | void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | 48 | Result Gesture::IsActive(bool& out_is_active) const { |
| 275 | GestureType& type, f32 time_difference) { | 49 | out_is_active = touch_resource->IsGestureActive(); |
| 276 | const auto& last_entry = GetLastGestureEntry(); | 50 | return ResultSuccess; |
| 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 | } | 51 | } |
| 365 | 52 | ||
| 366 | } // namespace Service::HID | 53 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/touch_screen/gesture.h b/src/hid_core/resources/touch_screen/gesture.h index 32e9a8690..d92912bb6 100644 --- a/src/hid_core/resources/touch_screen/gesture.h +++ b/src/hid_core/resources/touch_screen/gesture.h | |||
| @@ -1,87 +1,32 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <mutex> |
| 7 | 7 | ||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "hid_core/resources/controller_base.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedConsole; | ||
| 14 | } | ||
| 15 | 10 | ||
| 16 | namespace Service::HID { | 11 | namespace Service::HID { |
| 17 | struct GestureSharedMemoryFormat; | 12 | class TouchResource; |
| 18 | 13 | ||
| 19 | class Gesture final : public ControllerBase { | 14 | /// Handles gesture request from HID interfaces |
| 15 | class Gesture { | ||
| 20 | public: | 16 | public: |
| 21 | explicit Gesture(Core::HID::HIDCore& hid_core_); | 17 | Gesture(std::shared_ptr<TouchResource> resource); |
| 22 | ~Gesture() override; | 18 | ~Gesture(); |
| 23 | 19 | ||
| 24 | // Called when the controller is initialized | 20 | Result Activate(); |
| 25 | void OnInit() override; | 21 | Result Activate(u64 aruid, u32 basic_gesture_id); |
| 26 | 22 | ||
| 27 | // When the controller is released | 23 | Result Deactivate(); |
| 28 | void OnRelease() override; | ||
| 29 | 24 | ||
| 30 | // When the controller is requesting an update for the shared memory | 25 | Result IsActive(bool& out_is_active) const; |
| 31 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 32 | 26 | ||
| 33 | private: | 27 | private: |
| 34 | // Reads input from all available input engines | 28 | mutable std::mutex mutex; |
| 35 | void ReadTouchInput(); | 29 | std::shared_ptr<TouchResource> touch_resource; |
| 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 | }; | 30 | }; |
| 31 | |||
| 87 | } // namespace Service::HID | 32 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/touch_screen/gesture_handler.cpp b/src/hid_core/resources/touch_screen/gesture_handler.cpp new file mode 100644 index 000000000..4fcaf6ecf --- /dev/null +++ b/src/hid_core/resources/touch_screen/gesture_handler.cpp | |||
| @@ -0,0 +1,260 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/math_util.h" | ||
| 5 | #include "hid_core/resources/touch_screen/gesture_handler.h" | ||
| 6 | |||
| 7 | namespace Service::HID { | ||
| 8 | |||
| 9 | constexpr f32 Square(s32 num) { | ||
| 10 | return static_cast<f32>(num * num); | ||
| 11 | } | ||
| 12 | |||
| 13 | GestureHandler::GestureHandler() {} | ||
| 14 | |||
| 15 | GestureHandler::~GestureHandler() {} | ||
| 16 | |||
| 17 | void GestureHandler::SetTouchState(std::span<TouchState> touch_state, u32 count, s64 timestamp) { | ||
| 18 | gesture = {}; | ||
| 19 | gesture.active_points = std::min(MaxPoints, static_cast<std::size_t>(count)); | ||
| 20 | |||
| 21 | for (size_t id = 0; id < gesture.active_points; ++id) { | ||
| 22 | const auto& [active_x, active_y] = touch_state[id].position; | ||
| 23 | gesture.points[id] = { | ||
| 24 | .x = static_cast<s32>(active_x), | ||
| 25 | .y = static_cast<s32>(active_y), | ||
| 26 | }; | ||
| 27 | |||
| 28 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); | ||
| 29 | gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points); | ||
| 30 | } | ||
| 31 | |||
| 32 | for (size_t id = 0; id < gesture.active_points; ++id) { | ||
| 33 | const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) + | ||
| 34 | Square(gesture.mid_point.y - gesture.points[id].y)); | ||
| 35 | gesture.average_distance += distance / static_cast<f32>(gesture.active_points); | ||
| 36 | } | ||
| 37 | |||
| 38 | gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y), | ||
| 39 | static_cast<f32>(gesture.mid_point.x - gesture.points[0].x)); | ||
| 40 | |||
| 41 | gesture.detection_count = last_gesture.detection_count; | ||
| 42 | |||
| 43 | if (last_update_timestamp > timestamp) { | ||
| 44 | timestamp = last_tap_timestamp; | ||
| 45 | } | ||
| 46 | |||
| 47 | time_difference = static_cast<f32>(timestamp - last_update_timestamp) / (1000 * 1000 * 1000); | ||
| 48 | } | ||
| 49 | |||
| 50 | bool GestureHandler::NeedsUpdate() { | ||
| 51 | if (force_update) { | ||
| 52 | force_update = false; | ||
| 53 | return true; | ||
| 54 | } | ||
| 55 | |||
| 56 | // Update if coordinates change | ||
| 57 | for (size_t id = 0; id < MaxPoints; id++) { | ||
| 58 | if (gesture.points[id] != last_gesture.points[id]) { | ||
| 59 | return true; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | // Update on press and hold event after 0.5 seconds | ||
| 64 | if (last_gesture_state.type == GestureType::Touch && last_gesture_state.point_count == 1 && | ||
| 65 | time_difference > PressDelay) { | ||
| 66 | return enable_press_and_tap; | ||
| 67 | } | ||
| 68 | |||
| 69 | return false; | ||
| 70 | } | ||
| 71 | |||
| 72 | void GestureHandler::UpdateGestureState(GestureState& next_state, s64 timestamp) { | ||
| 73 | last_update_timestamp = timestamp; | ||
| 74 | |||
| 75 | GestureType type = GestureType::Idle; | ||
| 76 | GestureAttribute attributes{}; | ||
| 77 | |||
| 78 | // Reset next state to default | ||
| 79 | next_state.sampling_number = last_gesture_state.sampling_number + 1; | ||
| 80 | next_state.delta = {}; | ||
| 81 | next_state.vel_x = 0; | ||
| 82 | next_state.vel_y = 0; | ||
| 83 | next_state.direction = GestureDirection::None; | ||
| 84 | next_state.rotation_angle = 0; | ||
| 85 | next_state.scale = 0; | ||
| 86 | |||
| 87 | if (gesture.active_points > 0) { | ||
| 88 | if (last_gesture.active_points == 0) { | ||
| 89 | NewGesture(type, attributes); | ||
| 90 | } else { | ||
| 91 | UpdateExistingGesture(next_state, type); | ||
| 92 | } | ||
| 93 | } else { | ||
| 94 | EndGesture(next_state, type, attributes); | ||
| 95 | } | ||
| 96 | |||
| 97 | // Apply attributes | ||
| 98 | next_state.detection_count = gesture.detection_count; | ||
| 99 | next_state.type = type; | ||
| 100 | next_state.attributes = attributes; | ||
| 101 | next_state.pos = gesture.mid_point; | ||
| 102 | next_state.point_count = static_cast<s32>(gesture.active_points); | ||
| 103 | next_state.points = gesture.points; | ||
| 104 | last_gesture = gesture; | ||
| 105 | last_gesture_state = next_state; | ||
| 106 | } | ||
| 107 | |||
| 108 | void GestureHandler::NewGesture(GestureType& type, GestureAttribute& attributes) { | ||
| 109 | gesture.detection_count++; | ||
| 110 | type = GestureType::Touch; | ||
| 111 | |||
| 112 | // New touch after cancel is not considered new | ||
| 113 | if (last_gesture_state.type != GestureType::Cancel) { | ||
| 114 | attributes.is_new_touch.Assign(1); | ||
| 115 | enable_press_and_tap = true; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | void GestureHandler::UpdateExistingGesture(GestureState& next_state, GestureType& type) { | ||
| 120 | // Promote to pan type if touch moved | ||
| 121 | for (size_t id = 0; id < MaxPoints; id++) { | ||
| 122 | if (gesture.points[id] != last_gesture.points[id]) { | ||
| 123 | type = GestureType::Pan; | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | // Number of fingers changed cancel the last event and clear data | ||
| 129 | if (gesture.active_points != last_gesture.active_points) { | ||
| 130 | type = GestureType::Cancel; | ||
| 131 | enable_press_and_tap = false; | ||
| 132 | gesture.active_points = 0; | ||
| 133 | gesture.mid_point = {}; | ||
| 134 | gesture.points.fill({}); | ||
| 135 | return; | ||
| 136 | } | ||
| 137 | |||
| 138 | // Calculate extra parameters of panning | ||
| 139 | if (type == GestureType::Pan) { | ||
| 140 | UpdatePanEvent(next_state, type); | ||
| 141 | return; | ||
| 142 | } | ||
| 143 | |||
| 144 | // Promote to press type | ||
| 145 | if (last_gesture_state.type == GestureType::Touch) { | ||
| 146 | type = GestureType::Press; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | void GestureHandler::EndGesture(GestureState& next_state, GestureType& type, | ||
| 151 | GestureAttribute& attributes) { | ||
| 152 | if (last_gesture.active_points != 0) { | ||
| 153 | switch (last_gesture_state.type) { | ||
| 154 | case GestureType::Touch: | ||
| 155 | if (enable_press_and_tap) { | ||
| 156 | SetTapEvent(type, attributes); | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | type = GestureType::Cancel; | ||
| 160 | force_update = true; | ||
| 161 | break; | ||
| 162 | case GestureType::Press: | ||
| 163 | case GestureType::Tap: | ||
| 164 | case GestureType::Swipe: | ||
| 165 | case GestureType::Pinch: | ||
| 166 | case GestureType::Rotate: | ||
| 167 | type = GestureType::Complete; | ||
| 168 | force_update = true; | ||
| 169 | break; | ||
| 170 | case GestureType::Pan: | ||
| 171 | EndPanEvent(next_state, type); | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | if (last_gesture_state.type == GestureType::Complete || | ||
| 179 | last_gesture_state.type == GestureType::Cancel) { | ||
| 180 | gesture.detection_count++; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | void GestureHandler::SetTapEvent(GestureType& type, GestureAttribute& attributes) { | ||
| 185 | type = GestureType::Tap; | ||
| 186 | gesture = last_gesture; | ||
| 187 | force_update = true; | ||
| 188 | f32 tap_time_difference = | ||
| 189 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); | ||
| 190 | last_tap_timestamp = last_update_timestamp; | ||
| 191 | if (tap_time_difference < DoubleTapDelay) { | ||
| 192 | attributes.is_double_tap.Assign(1); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | void GestureHandler::UpdatePanEvent(GestureState& next_state, GestureType& type) { | ||
| 197 | next_state.delta = gesture.mid_point - last_gesture_state.pos; | ||
| 198 | next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference; | ||
| 199 | next_state.vel_y = static_cast<f32>(next_state.delta.y) / time_difference; | ||
| 200 | last_pan_time_difference = time_difference; | ||
| 201 | |||
| 202 | // Promote to pinch type | ||
| 203 | if (std::abs(gesture.average_distance - last_gesture.average_distance) > PinchThreshold) { | ||
| 204 | type = GestureType::Pinch; | ||
| 205 | next_state.scale = gesture.average_distance / last_gesture.average_distance; | ||
| 206 | } | ||
| 207 | |||
| 208 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture.angle) / | ||
| 209 | (1 + (gesture.angle * last_gesture.angle))); | ||
| 210 | // Promote to rotate type | ||
| 211 | if (std::abs(angle_between_two_lines) > AngleThreshold) { | ||
| 212 | type = GestureType::Rotate; | ||
| 213 | next_state.scale = 0; | ||
| 214 | next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | void GestureHandler::EndPanEvent(GestureState& next_state, GestureType& type) { | ||
| 219 | next_state.vel_x = | ||
| 220 | static_cast<f32>(last_gesture_state.delta.x) / (last_pan_time_difference + time_difference); | ||
| 221 | next_state.vel_y = | ||
| 222 | static_cast<f32>(last_gesture_state.delta.y) / (last_pan_time_difference + time_difference); | ||
| 223 | const f32 curr_vel = | ||
| 224 | std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); | ||
| 225 | |||
| 226 | // Set swipe event with parameters | ||
| 227 | if (curr_vel > SwipeThreshold) { | ||
| 228 | SetSwipeEvent(next_state, type); | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | |||
| 232 | // End panning without swipe | ||
| 233 | type = GestureType::Complete; | ||
| 234 | next_state.vel_x = 0; | ||
| 235 | next_state.vel_y = 0; | ||
| 236 | force_update = true; | ||
| 237 | } | ||
| 238 | |||
| 239 | void GestureHandler::SetSwipeEvent(GestureState& next_state, GestureType& type) { | ||
| 240 | type = GestureType::Swipe; | ||
| 241 | gesture = last_gesture; | ||
| 242 | force_update = true; | ||
| 243 | next_state.delta = last_gesture_state.delta; | ||
| 244 | |||
| 245 | if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { | ||
| 246 | if (next_state.delta.x > 0) { | ||
| 247 | next_state.direction = GestureDirection::Right; | ||
| 248 | return; | ||
| 249 | } | ||
| 250 | next_state.direction = GestureDirection::Left; | ||
| 251 | return; | ||
| 252 | } | ||
| 253 | if (next_state.delta.y > 0) { | ||
| 254 | next_state.direction = GestureDirection::Down; | ||
| 255 | return; | ||
| 256 | } | ||
| 257 | next_state.direction = GestureDirection::Up; | ||
| 258 | } | ||
| 259 | |||
| 260 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/touch_screen/gesture_handler.h b/src/hid_core/resources/touch_screen/gesture_handler.h new file mode 100644 index 000000000..fda2040c9 --- /dev/null +++ b/src/hid_core/resources/touch_screen/gesture_handler.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <span> | ||
| 7 | |||
| 8 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | class GestureHandler { | ||
| 13 | public: | ||
| 14 | GestureHandler(); | ||
| 15 | ~GestureHandler(); | ||
| 16 | |||
| 17 | void SetTouchState(std::span<TouchState> touch_state, u32 count, s64 timestamp); | ||
| 18 | |||
| 19 | bool NeedsUpdate(); | ||
| 20 | void UpdateGestureState(GestureState& next_state, s64 timestamp); | ||
| 21 | |||
| 22 | private: | ||
| 23 | // Initializes new gesture | ||
| 24 | void NewGesture(GestureType& type, GestureAttribute& attributes); | ||
| 25 | |||
| 26 | // Updates existing gesture state | ||
| 27 | void UpdateExistingGesture(GestureState& next_state, GestureType& type); | ||
| 28 | |||
| 29 | // Terminates exiting gesture | ||
| 30 | void EndGesture(GestureState& next_state, GestureType& type, GestureAttribute& attributes); | ||
| 31 | |||
| 32 | // Set current event to a tap event | ||
| 33 | void SetTapEvent(GestureType& type, GestureAttribute& attributes); | ||
| 34 | |||
| 35 | // Calculates and set the extra parameters related to a pan event | ||
| 36 | void UpdatePanEvent(GestureState& next_state, GestureType& type); | ||
| 37 | |||
| 38 | // Terminates the pan event | ||
| 39 | void EndPanEvent(GestureState& next_state, GestureType& type); | ||
| 40 | |||
| 41 | // Set current event to a swipe event | ||
| 42 | void SetSwipeEvent(GestureState& next_state, GestureType& type); | ||
| 43 | |||
| 44 | GestureProperties gesture{}; | ||
| 45 | GestureProperties last_gesture{}; | ||
| 46 | GestureState last_gesture_state{}; | ||
| 47 | s64 last_update_timestamp{}; | ||
| 48 | s64 last_tap_timestamp{}; | ||
| 49 | f32 last_pan_time_difference{}; | ||
| 50 | f32 time_difference{}; | ||
| 51 | bool force_update{true}; | ||
| 52 | bool enable_press_and_tap{false}; | ||
| 53 | }; | ||
| 54 | |||
| 55 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/touch_screen/gesture_types.h b/src/hid_core/resources/touch_screen/gesture_types.h deleted file mode 100644 index b4f034cd3..000000000 --- a/src/hid_core/resources/touch_screen/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/hid_core/resources/touch_screen/touch_screen.cpp b/src/hid_core/resources/touch_screen/touch_screen.cpp index 48d956c51..35efb1786 100644 --- a/src/hid_core/resources/touch_screen/touch_screen.cpp +++ b/src/hid_core/resources/touch_screen/touch_screen.cpp | |||
| @@ -1,132 +1,119 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include "hid_core/hid_types.h" |
| 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 "hid_core/frontend/emulated_console.h" | ||
| 10 | #include "hid_core/hid_core.h" | ||
| 11 | #include "hid_core/resources/applet_resource.h" | ||
| 12 | #include "hid_core/resources/shared_memory_format.h" | ||
| 13 | #include "hid_core/resources/touch_screen/touch_screen.h" | 5 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 6 | #include "hid_core/resources/touch_screen/touch_screen_resource.h" | ||
| 14 | 7 | ||
| 15 | namespace Service::HID { | 8 | namespace Service::HID { |
| 16 | 9 | ||
| 17 | TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_) | 10 | TouchScreen::TouchScreen(std::shared_ptr<TouchResource> resource) : touch_resource{resource} {} |
| 18 | : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), | ||
| 19 | touchscreen_height(Layout::ScreenUndocked::Height) { | ||
| 20 | console = hid_core.GetEmulatedConsole(); | ||
| 21 | } | ||
| 22 | 11 | ||
| 23 | TouchScreen::~TouchScreen() = default; | 12 | TouchScreen::~TouchScreen() = default; |
| 24 | 13 | ||
| 25 | void TouchScreen::OnInit() {} | 14 | Result TouchScreen::Activate() { |
| 15 | std::scoped_lock lock{mutex}; | ||
| 26 | 16 | ||
| 27 | void TouchScreen::OnRelease() {} | 17 | // TODO: Result result = CreateThread(); |
| 28 | 18 | Result result = ResultSuccess; | |
| 29 | void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | 19 | if (result.IsError()) { |
| 30 | const u64 aruid = applet_resource->GetActiveAruid(); | 20 | return result; |
| 31 | auto* data = applet_resource->GetAruidData(aruid); | 21 | } |
| 32 | 22 | ||
| 33 | if (data == nullptr || !data->flag.is_assigned) { | 23 | result = touch_resource->ActivateTouch(); |
| 34 | return; | 24 | if (result.IsError()) { |
| 25 | // TODO: StopThread(); | ||
| 35 | } | 26 | } |
| 36 | 27 | ||
| 37 | TouchScreenSharedMemoryFormat& shared_memory = data->shared_memory_format->touch_screen; | 28 | return result; |
| 38 | shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); | 29 | } |
| 39 | 30 | ||
| 40 | if (!IsControllerActivated()) { | 31 | Result TouchScreen::Activate(u64 aruid) { |
| 41 | shared_memory.touch_screen_lifo.buffer_count = 0; | 32 | std::scoped_lock lock{mutex}; |
| 42 | shared_memory.touch_screen_lifo.buffer_tail = 0; | 33 | return touch_resource->ActivateTouch(aruid); |
| 43 | return; | 34 | } |
| 44 | } | ||
| 45 | 35 | ||
| 46 | const auto touch_status = console->GetTouch(); | 36 | Result TouchScreen::Deactivate() { |
| 47 | for (std::size_t id = 0; id < MAX_FINGERS; id++) { | 37 | std::scoped_lock lock{mutex}; |
| 48 | const auto& current_touch = touch_status[id]; | 38 | const auto result = touch_resource->DeactivateTouch(); |
| 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 | 39 | ||
| 85 | std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers; | 40 | if (result.IsError()) { |
| 86 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | 41 | return result; |
| 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 | } | 42 | } |
| 123 | 43 | ||
| 124 | shared_memory.touch_screen_lifo.WriteNextEntry(next_state); | 44 | // TODO: return StopThread(); |
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | |||
| 48 | Result TouchScreen::IsActive(bool& out_is_active) const { | ||
| 49 | out_is_active = touch_resource->IsTouchActive(); | ||
| 50 | return ResultSuccess; | ||
| 51 | } | ||
| 52 | |||
| 53 | Result TouchScreen::SetTouchScreenAutoPilotState(const AutoPilotState& auto_pilot_state) { | ||
| 54 | std::scoped_lock lock{mutex}; | ||
| 55 | return touch_resource->SetTouchScreenAutoPilotState(auto_pilot_state); | ||
| 56 | } | ||
| 57 | |||
| 58 | Result TouchScreen::UnsetTouchScreenAutoPilotState() { | ||
| 59 | std::scoped_lock lock{mutex}; | ||
| 60 | return touch_resource->UnsetTouchScreenAutoPilotState(); | ||
| 61 | } | ||
| 62 | |||
| 63 | Result TouchScreen::RequestNextTouchInput() { | ||
| 64 | std::scoped_lock lock{mutex}; | ||
| 65 | return touch_resource->RequestNextTouchInput(); | ||
| 66 | } | ||
| 67 | |||
| 68 | Result TouchScreen::RequestNextDummyInput() { | ||
| 69 | std::scoped_lock lock{mutex}; | ||
| 70 | return touch_resource->RequestNextDummyInput(); | ||
| 71 | } | ||
| 72 | |||
| 73 | Result TouchScreen::ProcessTouchScreenAutoTune() { | ||
| 74 | std::scoped_lock lock{mutex}; | ||
| 75 | return touch_resource->ProcessTouchScreenAutoTune(); | ||
| 76 | } | ||
| 77 | |||
| 78 | Result TouchScreen::SetTouchScreenMagnification(f32 point1_x, f32 point1_y, f32 point2_x, | ||
| 79 | f32 point2_y) { | ||
| 80 | std::scoped_lock lock{mutex}; | ||
| 81 | touch_resource->SetTouchScreenMagnification(point1_x, point1_y, point2_x, point2_y); | ||
| 82 | return ResultSuccess; | ||
| 83 | } | ||
| 84 | |||
| 85 | Result TouchScreen::SetTouchScreenResolution(u32 width, u32 height, u64 aruid) { | ||
| 86 | std::scoped_lock lock{mutex}; | ||
| 87 | return touch_resource->SetTouchScreenResolution(width, height, aruid); | ||
| 88 | } | ||
| 89 | |||
| 90 | Result TouchScreen::SetTouchScreenConfiguration( | ||
| 91 | const Core::HID::TouchScreenConfigurationForNx& mode, u64 aruid) { | ||
| 92 | std::scoped_lock lock{mutex}; | ||
| 93 | return touch_resource->SetTouchScreenConfiguration(mode, aruid); | ||
| 94 | } | ||
| 95 | |||
| 96 | Result TouchScreen::GetTouchScreenConfiguration(Core::HID::TouchScreenConfigurationForNx& out_mode, | ||
| 97 | u64 aruid) const { | ||
| 98 | std::scoped_lock lock{mutex}; | ||
| 99 | return touch_resource->GetTouchScreenConfiguration(out_mode, aruid); | ||
| 100 | } | ||
| 101 | |||
| 102 | Result TouchScreen::SetTouchScreenDefaultConfiguration( | ||
| 103 | const Core::HID::TouchScreenConfigurationForNx& mode) { | ||
| 104 | std::scoped_lock lock{mutex}; | ||
| 105 | return touch_resource->SetTouchScreenDefaultConfiguration(mode); | ||
| 106 | } | ||
| 107 | |||
| 108 | Result TouchScreen::GetTouchScreenDefaultConfiguration( | ||
| 109 | Core::HID::TouchScreenConfigurationForNx& out_mode) const { | ||
| 110 | std::scoped_lock lock{mutex}; | ||
| 111 | return touch_resource->GetTouchScreenDefaultConfiguration(out_mode); | ||
| 125 | } | 112 | } |
| 126 | 113 | ||
| 127 | void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { | 114 | void TouchScreen::OnTouchUpdate(u64 timestamp) { |
| 128 | touchscreen_width = width; | 115 | std::scoped_lock lock{mutex}; |
| 129 | touchscreen_height = height; | 116 | touch_resource->OnTouchUpdate(timestamp); |
| 130 | } | 117 | } |
| 131 | 118 | ||
| 132 | } // namespace Service::HID | 119 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/touch_screen/touch_screen.h b/src/hid_core/resources/touch_screen/touch_screen.h index 4b3824742..2fcb6247f 100644 --- a/src/hid_core/resources/touch_screen/touch_screen.h +++ b/src/hid_core/resources/touch_screen/touch_screen.h | |||
| @@ -1,43 +1,64 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <mutex> |
| 7 | 7 | ||
| 8 | #include "hid_core/hid_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "hid_core/resources/controller_base.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 11 | 10 | ||
| 12 | namespace Core::HID { | 11 | namespace Core::HID { |
| 13 | class EmulatedConsole; | 12 | struct TouchScreenConfigurationForNx; |
| 14 | } // namespace Core::HID | 13 | } |
| 14 | |||
| 15 | namespace Core::Timing { | ||
| 16 | struct EventType; | ||
| 17 | } | ||
| 15 | 18 | ||
| 16 | namespace Service::HID { | 19 | namespace Service::HID { |
| 17 | struct TouchScreenSharedMemoryFormat; | 20 | class TouchResource; |
| 21 | struct AutoPilotState; | ||
| 18 | 22 | ||
| 19 | class TouchScreen final : public ControllerBase { | 23 | /// Handles touch request from HID interfaces |
| 24 | class TouchScreen { | ||
| 20 | public: | 25 | public: |
| 21 | explicit TouchScreen(Core::HID::HIDCore& hid_core_); | 26 | TouchScreen(std::shared_ptr<TouchResource> resource); |
| 22 | ~TouchScreen() override; | 27 | ~TouchScreen(); |
| 23 | 28 | ||
| 24 | // Called when the controller is initialized | 29 | Result Activate(); |
| 25 | void OnInit() override; | 30 | Result Activate(u64 aruid); |
| 26 | 31 | ||
| 27 | // When the controller is released | 32 | Result Deactivate(); |
| 28 | void OnRelease() override; | ||
| 29 | 33 | ||
| 30 | // When the controller is requesting an update for the shared memory | 34 | Result IsActive(bool& out_is_active) const; |
| 31 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 32 | 35 | ||
| 33 | void SetTouchscreenDimensions(u32 width, u32 height); | 36 | Result SetTouchScreenAutoPilotState(const AutoPilotState& auto_pilot_state); |
| 37 | Result UnsetTouchScreenAutoPilotState(); | ||
| 34 | 38 | ||
| 35 | private: | 39 | Result RequestNextTouchInput(); |
| 36 | TouchScreenState next_state{}; | 40 | Result RequestNextDummyInput(); |
| 37 | Core::HID::EmulatedConsole* console = nullptr; | 41 | |
| 42 | Result ProcessTouchScreenAutoTune(); | ||
| 43 | |||
| 44 | Result SetTouchScreenMagnification(f32 point1_x, f32 point1_y, f32 point2_x, f32 point2_y); | ||
| 45 | Result SetTouchScreenResolution(u32 width, u32 height, u64 aruid); | ||
| 46 | |||
| 47 | Result SetTouchScreenConfiguration(const Core::HID::TouchScreenConfigurationForNx& mode, | ||
| 48 | u64 aruid); | ||
| 49 | Result GetTouchScreenConfiguration(Core::HID::TouchScreenConfigurationForNx& out_mode, | ||
| 50 | u64 aruid) const; | ||
| 38 | 51 | ||
| 39 | std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; | 52 | Result SetTouchScreenDefaultConfiguration(const Core::HID::TouchScreenConfigurationForNx& mode); |
| 40 | u32 touchscreen_width; | 53 | Result GetTouchScreenDefaultConfiguration( |
| 41 | u32 touchscreen_height; | 54 | Core::HID::TouchScreenConfigurationForNx& out_mode) const; |
| 55 | |||
| 56 | void OnTouchUpdate(u64 timestamp); | ||
| 57 | |||
| 58 | private: | ||
| 59 | mutable std::mutex mutex; | ||
| 60 | std::shared_ptr<TouchResource> touch_resource; | ||
| 61 | std::shared_ptr<Core::Timing::EventType> touch_update_event; | ||
| 42 | }; | 62 | }; |
| 63 | |||
| 43 | } // namespace Service::HID | 64 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/touch_screen/touch_screen_driver.cpp b/src/hid_core/resources/touch_screen/touch_screen_driver.cpp new file mode 100644 index 000000000..6a64c75b3 --- /dev/null +++ b/src/hid_core/resources/touch_screen/touch_screen_driver.cpp | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include "common/settings.h" | ||
| 6 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "hid_core/hid_core.h" | ||
| 8 | #include "hid_core/resources/touch_screen/touch_screen_driver.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | TouchDriver::TouchDriver(Core::HID::HIDCore& hid_core) { | ||
| 13 | console = hid_core.GetEmulatedConsole(); | ||
| 14 | } | ||
| 15 | |||
| 16 | TouchDriver::~TouchDriver() = default; | ||
| 17 | |||
| 18 | Result TouchDriver::StartTouchSensor() { | ||
| 19 | is_running = true; | ||
| 20 | return ResultSuccess; | ||
| 21 | } | ||
| 22 | |||
| 23 | Result TouchDriver::StopTouchSensor() { | ||
| 24 | is_running = false; | ||
| 25 | return ResultSuccess; | ||
| 26 | } | ||
| 27 | |||
| 28 | bool TouchDriver::IsRunning() const { | ||
| 29 | return is_running; | ||
| 30 | } | ||
| 31 | |||
| 32 | void TouchDriver::ProcessTouchScreenAutoTune() const { | ||
| 33 | // TODO | ||
| 34 | } | ||
| 35 | |||
| 36 | Result TouchDriver::WaitForDummyInput() { | ||
| 37 | touch_status = {}; | ||
| 38 | return ResultSuccess; | ||
| 39 | } | ||
| 40 | |||
| 41 | Result TouchDriver::WaitForInput() { | ||
| 42 | touch_status = {}; | ||
| 43 | const auto touch_input = console->GetTouch(); | ||
| 44 | for (std::size_t id = 0; id < touch_status.states.size(); id++) { | ||
| 45 | const auto& current_touch = touch_input[id]; | ||
| 46 | auto& finger = fingers[id]; | ||
| 47 | finger.id = current_touch.id; | ||
| 48 | |||
| 49 | if (finger.attribute.start_touch) { | ||
| 50 | finger.attribute.raw = 0; | ||
| 51 | continue; | ||
| 52 | } | ||
| 53 | |||
| 54 | if (finger.attribute.end_touch) { | ||
| 55 | finger.attribute.raw = 0; | ||
| 56 | finger.pressed = false; | ||
| 57 | continue; | ||
| 58 | } | ||
| 59 | |||
| 60 | if (!finger.pressed && current_touch.pressed) { | ||
| 61 | finger.attribute.start_touch.Assign(1); | ||
| 62 | finger.pressed = true; | ||
| 63 | finger.position = current_touch.position; | ||
| 64 | continue; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (finger.pressed && !current_touch.pressed) { | ||
| 68 | finger.attribute.raw = 0; | ||
| 69 | finger.attribute.end_touch.Assign(1); | ||
| 70 | continue; | ||
| 71 | } | ||
| 72 | |||
| 73 | // Only update position if touch is not on a special frame | ||
| 74 | finger.position = current_touch.position; | ||
| 75 | } | ||
| 76 | |||
| 77 | std::array<Core::HID::TouchFinger, MaxFingers> active_fingers; | ||
| 78 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 79 | [](const auto& finger) { return finger.pressed; }); | ||
| 80 | const auto active_fingers_count = | ||
| 81 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 82 | |||
| 83 | touch_status.entry_count = static_cast<s32>(active_fingers_count); | ||
| 84 | for (std::size_t id = 0; id < MaxFingers; ++id) { | ||
| 85 | auto& touch_entry = touch_status.states[id]; | ||
| 86 | if (id < active_fingers_count) { | ||
| 87 | const auto& [active_x, active_y] = active_fingers[id].position; | ||
| 88 | touch_entry.position = { | ||
| 89 | .x = static_cast<u16>(active_x * TouchSensorWidth), | ||
| 90 | .y = static_cast<u16>(active_y * TouchSensorHeight), | ||
| 91 | }; | ||
| 92 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | ||
| 93 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | ||
| 94 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | ||
| 95 | touch_entry.finger = active_fingers[id].id; | ||
| 96 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return ResultSuccess; | ||
| 100 | } | ||
| 101 | |||
| 102 | void TouchDriver::GetNextTouchState(TouchScreenState& out_state) const { | ||
| 103 | out_state = touch_status; | ||
| 104 | } | ||
| 105 | |||
| 106 | void TouchDriver::SetTouchMode(Core::HID::TouchScreenModeForNx mode) { | ||
| 107 | touch_mode = mode; | ||
| 108 | } | ||
| 109 | |||
| 110 | Core::HID::TouchScreenModeForNx TouchDriver::GetTouchMode() const { | ||
| 111 | return touch_mode; | ||
| 112 | } | ||
| 113 | |||
| 114 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/touch_screen/touch_screen_driver.h b/src/hid_core/resources/touch_screen/touch_screen_driver.h new file mode 100644 index 000000000..ca7e4970e --- /dev/null +++ b/src/hid_core/resources/touch_screen/touch_screen_driver.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/frontend/emulated_console.h" | ||
| 9 | #include "hid_core/hid_types.h" | ||
| 10 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class HIDCore; | ||
| 14 | } // namespace Core::HID | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | |||
| 18 | /// This handles all request to Ftm3bd56(TouchPanel) hardware | ||
| 19 | class TouchDriver { | ||
| 20 | public: | ||
| 21 | explicit TouchDriver(Core::HID::HIDCore& hid_core); | ||
| 22 | ~TouchDriver(); | ||
| 23 | |||
| 24 | Result StartTouchSensor(); | ||
| 25 | Result StopTouchSensor(); | ||
| 26 | bool IsRunning() const; | ||
| 27 | |||
| 28 | void ProcessTouchScreenAutoTune() const; | ||
| 29 | |||
| 30 | Result WaitForDummyInput(); | ||
| 31 | Result WaitForInput(); | ||
| 32 | |||
| 33 | void GetNextTouchState(TouchScreenState& out_state) const; | ||
| 34 | |||
| 35 | void SetTouchMode(Core::HID::TouchScreenModeForNx mode); | ||
| 36 | Core::HID::TouchScreenModeForNx GetTouchMode() const; | ||
| 37 | |||
| 38 | private: | ||
| 39 | bool is_running{}; | ||
| 40 | TouchScreenState touch_status{}; | ||
| 41 | Core::HID::TouchFingerState fingers{}; | ||
| 42 | Core::HID::TouchScreenModeForNx touch_mode{}; | ||
| 43 | |||
| 44 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp new file mode 100644 index 000000000..56e8e8e51 --- /dev/null +++ b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp | |||
| @@ -0,0 +1,579 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hle/kernel/k_event.h" | ||
| 7 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 8 | #include "core/hle/service/set/system_settings_server.h" | ||
| 9 | #include "core/hle/service/sm/sm.h" | ||
| 10 | #include "hid_core/hid_result.h" | ||
| 11 | #include "hid_core/resources/applet_resource.h" | ||
| 12 | #include "hid_core/resources/shared_memory_format.h" | ||
| 13 | #include "hid_core/resources/touch_screen/touch_screen_driver.h" | ||
| 14 | #include "hid_core/resources/touch_screen/touch_screen_resource.h" | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | constexpr auto GestureUpdatePeriod = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) | ||
| 18 | |||
| 19 | TouchResource::TouchResource(Core::System& system_) : system{system_} { | ||
| 20 | m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys"); | ||
| 21 | } | ||
| 22 | |||
| 23 | TouchResource::~TouchResource() { | ||
| 24 | Finalize(); | ||
| 25 | }; | ||
| 26 | |||
| 27 | Result TouchResource::ActivateTouch() { | ||
| 28 | if (global_ref_counter == std::numeric_limits<s32>::max() - 1 || | ||
| 29 | touch_ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 30 | return ResultTouchOverflow; | ||
| 31 | } | ||
| 32 | |||
| 33 | if (global_ref_counter == 0) { | ||
| 34 | std::scoped_lock lock{*shared_mutex}; | ||
| 35 | |||
| 36 | const auto result = touch_driver->StartTouchSensor(); | ||
| 37 | if (result.IsError()) { | ||
| 38 | return result; | ||
| 39 | } | ||
| 40 | |||
| 41 | is_initalized = true; | ||
| 42 | system.CoreTiming().ScheduleLoopingEvent(GestureUpdatePeriod, GestureUpdatePeriod, | ||
| 43 | timer_event); | ||
| 44 | current_touch_state = {}; | ||
| 45 | ReadTouchInput(); | ||
| 46 | gesture_handler.SetTouchState(current_touch_state.states, current_touch_state.entry_count, | ||
| 47 | 0); | ||
| 48 | } | ||
| 49 | |||
| 50 | Set::TouchScreenMode touch_mode{Set::TouchScreenMode::Standard}; | ||
| 51 | m_set_sys->GetTouchScreenMode(touch_mode); | ||
| 52 | default_touch_screen_mode = static_cast<Core::HID::TouchScreenModeForNx>(touch_mode); | ||
| 53 | |||
| 54 | global_ref_counter++; | ||
| 55 | touch_ref_counter++; | ||
| 56 | return ResultSuccess; | ||
| 57 | } | ||
| 58 | |||
| 59 | Result TouchResource::ActivateTouch(u64 aruid) { | ||
| 60 | std::scoped_lock lock{*shared_mutex}; | ||
| 61 | |||
| 62 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 63 | auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 64 | TouchAruidData& touch_data = aruid_data[aruid_index]; | ||
| 65 | |||
| 66 | if (!applet_data->flag.is_assigned) { | ||
| 67 | touch_data = {}; | ||
| 68 | continue; | ||
| 69 | } | ||
| 70 | |||
| 71 | const u64 aruid_id = applet_data->aruid; | ||
| 72 | if (touch_data.aruid != aruid_id) { | ||
| 73 | touch_data = {}; | ||
| 74 | touch_data.aruid = aruid_id; | ||
| 75 | } | ||
| 76 | |||
| 77 | if (aruid != aruid_id) { | ||
| 78 | continue; | ||
| 79 | } | ||
| 80 | |||
| 81 | auto& touch_shared = applet_data->shared_memory_format->touch_screen; | ||
| 82 | |||
| 83 | if (touch_shared.touch_screen_lifo.buffer_count == 0) { | ||
| 84 | StorePreviousTouchState(previous_touch_state, touch_data.finger_map, | ||
| 85 | current_touch_state, | ||
| 86 | applet_data->flag.enable_touchscreen.Value() != 0); | ||
| 87 | touch_shared.touch_screen_lifo.WriteNextEntry(previous_touch_state); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | return ResultSuccess; | ||
| 91 | } | ||
| 92 | |||
| 93 | Result TouchResource::ActivateGesture() { | ||
| 94 | if (global_ref_counter == std::numeric_limits<s32>::max() - 1 || | ||
| 95 | gesture_ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 96 | return ResultGestureOverflow; | ||
| 97 | } | ||
| 98 | |||
| 99 | // Initialize first instance | ||
| 100 | if (global_ref_counter == 0) { | ||
| 101 | const auto result = touch_driver->StartTouchSensor(); | ||
| 102 | if (result.IsError()) { | ||
| 103 | return result; | ||
| 104 | } | ||
| 105 | |||
| 106 | is_initalized = true; | ||
| 107 | system.CoreTiming().ScheduleLoopingEvent(GestureUpdatePeriod, GestureUpdatePeriod, | ||
| 108 | timer_event); | ||
| 109 | current_touch_state = {}; | ||
| 110 | ReadTouchInput(); | ||
| 111 | gesture_handler.SetTouchState(current_touch_state.states, current_touch_state.entry_count, | ||
| 112 | 0); | ||
| 113 | } | ||
| 114 | |||
| 115 | global_ref_counter++; | ||
| 116 | gesture_ref_counter++; | ||
| 117 | return ResultSuccess; | ||
| 118 | } | ||
| 119 | |||
| 120 | Result TouchResource::ActivateGesture(u64 aruid, u32 basic_gesture_id) { | ||
| 121 | std::scoped_lock lock{*shared_mutex}; | ||
| 122 | |||
| 123 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 124 | auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 125 | TouchAruidData& touch_data = aruid_data[aruid_index]; | ||
| 126 | |||
| 127 | if (!applet_data->flag.is_assigned) { | ||
| 128 | touch_data = {}; | ||
| 129 | continue; | ||
| 130 | } | ||
| 131 | |||
| 132 | const u64 aruid_id = applet_data->aruid; | ||
| 133 | if (touch_data.aruid != aruid_id) { | ||
| 134 | touch_data = {}; | ||
| 135 | touch_data.aruid = aruid_id; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (aruid != aruid_id) { | ||
| 139 | continue; | ||
| 140 | } | ||
| 141 | |||
| 142 | auto& gesture_shared = applet_data->shared_memory_format->gesture; | ||
| 143 | if (touch_data.basic_gesture_id != basic_gesture_id) { | ||
| 144 | gesture_shared.gesture_lifo.buffer_count = 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (gesture_shared.gesture_lifo.buffer_count == 0) { | ||
| 148 | touch_data.basic_gesture_id = basic_gesture_id; | ||
| 149 | |||
| 150 | gesture_shared.gesture_lifo.WriteNextEntry(gesture_state); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | return ResultSuccess; | ||
| 155 | } | ||
| 156 | |||
| 157 | Result TouchResource::DeactivateTouch() { | ||
| 158 | if (touch_ref_counter == 0 || global_ref_counter == 0) { | ||
| 159 | return ResultTouchNotInitialized; | ||
| 160 | } | ||
| 161 | |||
| 162 | global_ref_counter--; | ||
| 163 | touch_ref_counter--; | ||
| 164 | |||
| 165 | if (touch_ref_counter + global_ref_counter != 0) { | ||
| 166 | return ResultSuccess; | ||
| 167 | } | ||
| 168 | |||
| 169 | return Finalize(); | ||
| 170 | } | ||
| 171 | |||
| 172 | Result TouchResource::DeactivateGesture() { | ||
| 173 | if (gesture_ref_counter == 0 || global_ref_counter == 0) { | ||
| 174 | return ResultGestureNotInitialized; | ||
| 175 | } | ||
| 176 | |||
| 177 | global_ref_counter--; | ||
| 178 | gesture_ref_counter--; | ||
| 179 | |||
| 180 | if (touch_ref_counter + global_ref_counter != 0) { | ||
| 181 | return ResultSuccess; | ||
| 182 | } | ||
| 183 | |||
| 184 | return Finalize(); | ||
| 185 | } | ||
| 186 | |||
| 187 | bool TouchResource::IsTouchActive() const { | ||
| 188 | return touch_ref_counter != 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | bool TouchResource::IsGestureActive() const { | ||
| 192 | return gesture_ref_counter != 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | void TouchResource::SetTouchDriver(std::shared_ptr<TouchDriver> driver) { | ||
| 196 | touch_driver = driver; | ||
| 197 | } | ||
| 198 | |||
| 199 | void TouchResource::SetAppletResource(std::shared_ptr<AppletResource> shared, | ||
| 200 | std::recursive_mutex* mutex) { | ||
| 201 | applet_resource = shared; | ||
| 202 | shared_mutex = mutex; | ||
| 203 | } | ||
| 204 | |||
| 205 | void TouchResource::SetInputEvent(Kernel::KEvent* event, std::mutex* mutex) { | ||
| 206 | input_event = event; | ||
| 207 | input_mutex = mutex; | ||
| 208 | } | ||
| 209 | |||
| 210 | void TouchResource::SetHandheldConfig(std::shared_ptr<HandheldConfig> config) { | ||
| 211 | handheld_config = config; | ||
| 212 | } | ||
| 213 | |||
| 214 | void TouchResource::SetTimerEvent(std::shared_ptr<Core::Timing::EventType> event) { | ||
| 215 | timer_event = event; | ||
| 216 | } | ||
| 217 | |||
| 218 | Result TouchResource::SetTouchScreenAutoPilotState(const AutoPilotState& auto_pilot_state) { | ||
| 219 | if (global_ref_counter == 0) { | ||
| 220 | return ResultTouchNotInitialized; | ||
| 221 | } | ||
| 222 | |||
| 223 | if (!is_auto_pilot_initialized) { | ||
| 224 | is_auto_pilot_initialized = true; | ||
| 225 | auto_pilot = {}; | ||
| 226 | } | ||
| 227 | |||
| 228 | TouchScreenState state = { | ||
| 229 | .entry_count = static_cast<s32>(auto_pilot_state.count), | ||
| 230 | .states = auto_pilot_state.state, | ||
| 231 | }; | ||
| 232 | |||
| 233 | SanitizeInput(state); | ||
| 234 | |||
| 235 | auto_pilot.count = state.entry_count; | ||
| 236 | auto_pilot.state = state.states; | ||
| 237 | return ResultSuccess; | ||
| 238 | } | ||
| 239 | |||
| 240 | Result TouchResource::UnsetTouchScreenAutoPilotState() { | ||
| 241 | if (global_ref_counter == 0) { | ||
| 242 | return ResultTouchNotInitialized; | ||
| 243 | } | ||
| 244 | |||
| 245 | is_auto_pilot_initialized = false; | ||
| 246 | auto_pilot = {}; | ||
| 247 | return ResultSuccess; | ||
| 248 | } | ||
| 249 | |||
| 250 | Result TouchResource::RequestNextTouchInput() { | ||
| 251 | if (global_ref_counter == 0) { | ||
| 252 | return ResultTouchNotInitialized; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (handheld_config->is_handheld_hid_enabled) { | ||
| 256 | const Result result = touch_driver->WaitForInput(); | ||
| 257 | if (result.IsError()) { | ||
| 258 | return result; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | is_initalized = true; | ||
| 263 | return ResultSuccess; | ||
| 264 | } | ||
| 265 | |||
| 266 | Result TouchResource::RequestNextDummyInput() { | ||
| 267 | if (global_ref_counter == 0) { | ||
| 268 | return ResultTouchNotInitialized; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (handheld_config->is_handheld_hid_enabled) { | ||
| 272 | const Result result = touch_driver->WaitForDummyInput(); | ||
| 273 | if (result.IsError()) { | ||
| 274 | return result; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | is_initalized = false; | ||
| 279 | return ResultSuccess; | ||
| 280 | } | ||
| 281 | |||
| 282 | Result TouchResource::ProcessTouchScreenAutoTune() { | ||
| 283 | touch_driver->ProcessTouchScreenAutoTune(); | ||
| 284 | return ResultSuccess; | ||
| 285 | } | ||
| 286 | |||
| 287 | void TouchResource::SetTouchScreenMagnification(f32 point1_x, f32 point1_y, f32 point2_x, | ||
| 288 | f32 point2_y) { | ||
| 289 | offset = { | ||
| 290 | .x = point1_x, | ||
| 291 | .y = point1_y, | ||
| 292 | }; | ||
| 293 | magnification = { | ||
| 294 | .x = point2_x, | ||
| 295 | .y = point2_y, | ||
| 296 | }; | ||
| 297 | } | ||
| 298 | |||
| 299 | Result TouchResource::SetTouchScreenResolution(u32 width, u32 height, u64 aruid) { | ||
| 300 | std::scoped_lock lock{*shared_mutex}; | ||
| 301 | |||
| 302 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 303 | const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 304 | TouchAruidData& data = aruid_data[aruid_index]; | ||
| 305 | |||
| 306 | if (!applet_data->flag.is_assigned) { | ||
| 307 | continue; | ||
| 308 | } | ||
| 309 | if (aruid != data.aruid) { | ||
| 310 | continue; | ||
| 311 | } | ||
| 312 | data.resolution_width = static_cast<u16>(width); | ||
| 313 | data.resolution_height = static_cast<u16>(height); | ||
| 314 | } | ||
| 315 | |||
| 316 | return ResultSuccess; | ||
| 317 | } | ||
| 318 | |||
| 319 | Result TouchResource::SetTouchScreenConfiguration( | ||
| 320 | const Core::HID::TouchScreenConfigurationForNx& touch_configuration, u64 aruid) { | ||
| 321 | std::scoped_lock lock{*shared_mutex}; | ||
| 322 | |||
| 323 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 324 | const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 325 | TouchAruidData& data = aruid_data[aruid_index]; | ||
| 326 | |||
| 327 | if (!applet_data->flag.is_assigned) { | ||
| 328 | continue; | ||
| 329 | } | ||
| 330 | if (aruid != data.aruid) { | ||
| 331 | continue; | ||
| 332 | } | ||
| 333 | data.finger_map.touch_mode = touch_configuration.mode; | ||
| 334 | } | ||
| 335 | |||
| 336 | return ResultSuccess; | ||
| 337 | } | ||
| 338 | |||
| 339 | Result TouchResource::GetTouchScreenConfiguration( | ||
| 340 | Core::HID::TouchScreenConfigurationForNx& out_touch_configuration, u64 aruid) const { | ||
| 341 | std::scoped_lock lock{*shared_mutex}; | ||
| 342 | |||
| 343 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 344 | const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 345 | const TouchAruidData& data = aruid_data[aruid_index]; | ||
| 346 | |||
| 347 | if (!applet_data->flag.is_assigned) { | ||
| 348 | continue; | ||
| 349 | } | ||
| 350 | if (aruid != data.aruid) { | ||
| 351 | continue; | ||
| 352 | } | ||
| 353 | out_touch_configuration.mode = data.finger_map.touch_mode; | ||
| 354 | } | ||
| 355 | |||
| 356 | return ResultSuccess; | ||
| 357 | } | ||
| 358 | |||
| 359 | Result TouchResource::SetTouchScreenDefaultConfiguration( | ||
| 360 | const Core::HID::TouchScreenConfigurationForNx& touch_configuration) { | ||
| 361 | default_touch_screen_mode = touch_configuration.mode; | ||
| 362 | return ResultSuccess; | ||
| 363 | } | ||
| 364 | |||
| 365 | Result TouchResource::GetTouchScreenDefaultConfiguration( | ||
| 366 | Core::HID::TouchScreenConfigurationForNx& out_touch_configuration) const { | ||
| 367 | out_touch_configuration.mode = default_touch_screen_mode; | ||
| 368 | return ResultSuccess; | ||
| 369 | } | ||
| 370 | |||
| 371 | Result TouchResource::Finalize() { | ||
| 372 | is_auto_pilot_initialized = false; | ||
| 373 | auto_pilot = {}; | ||
| 374 | system.CoreTiming().UnscheduleEvent(timer_event); | ||
| 375 | |||
| 376 | const auto result = touch_driver->StopTouchSensor(); | ||
| 377 | if (result.IsError()) { | ||
| 378 | return result; | ||
| 379 | } | ||
| 380 | |||
| 381 | is_initalized = false; | ||
| 382 | return ResultSuccess; | ||
| 383 | } | ||
| 384 | |||
| 385 | void TouchResource::StorePreviousTouchState(TouchScreenState& out_previous_touch, | ||
| 386 | TouchFingerMap& out_finger_map, | ||
| 387 | const TouchScreenState& current_touch, | ||
| 388 | bool is_touch_enabled) const { | ||
| 389 | s32 finger_count{}; | ||
| 390 | |||
| 391 | if (is_touch_enabled) { | ||
| 392 | finger_count = current_touch.entry_count; | ||
| 393 | if (finger_count < 1) { | ||
| 394 | out_finger_map.finger_count = 0; | ||
| 395 | out_finger_map.finger_ids = {}; | ||
| 396 | out_previous_touch.sampling_number = current_touch.sampling_number; | ||
| 397 | out_previous_touch.entry_count = 0; | ||
| 398 | out_previous_touch.states = {}; | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | for (std::size_t i = 0; i < static_cast<u32>(finger_count); i++) { | ||
| 402 | out_finger_map.finger_ids[i] = current_touch.states[i].finger; | ||
| 403 | out_previous_touch.states[i] = current_touch.states[i]; | ||
| 404 | } | ||
| 405 | out_finger_map.finger_count = finger_count; | ||
| 406 | return; | ||
| 407 | } | ||
| 408 | |||
| 409 | if (!is_touch_enabled && out_finger_map.finger_count > 0 && current_touch.entry_count > 0) { | ||
| 410 | // TODO | ||
| 411 | } | ||
| 412 | |||
| 413 | // Zero out unused entries | ||
| 414 | for (std::size_t i = finger_count; i < MaxFingers; i++) { | ||
| 415 | out_finger_map.finger_ids[i] = 0; | ||
| 416 | out_previous_touch.states[i] = {}; | ||
| 417 | } | ||
| 418 | |||
| 419 | out_previous_touch.sampling_number = current_touch.sampling_number; | ||
| 420 | out_previous_touch.entry_count = finger_count; | ||
| 421 | } | ||
| 422 | |||
| 423 | void TouchResource::ReadTouchInput() { | ||
| 424 | previous_touch_state = current_touch_state; | ||
| 425 | |||
| 426 | if (!is_initalized || !handheld_config->is_handheld_hid_enabled || !touch_driver->IsRunning()) { | ||
| 427 | touch_driver->WaitForDummyInput(); | ||
| 428 | } else { | ||
| 429 | touch_driver->WaitForInput(); | ||
| 430 | } | ||
| 431 | |||
| 432 | touch_driver->GetNextTouchState(current_touch_state); | ||
| 433 | SanitizeInput(current_touch_state); | ||
| 434 | current_touch_state.sampling_number = sample_number; | ||
| 435 | sample_number++; | ||
| 436 | |||
| 437 | if (is_auto_pilot_initialized && current_touch_state.entry_count == 0) { | ||
| 438 | const std::size_t finger_count = static_cast<std::size_t>(auto_pilot.count); | ||
| 439 | current_touch_state.entry_count = static_cast<s32>(finger_count); | ||
| 440 | for (std::size_t i = 0; i < finger_count; i++) { | ||
| 441 | current_touch_state.states[i] = auto_pilot.state[i]; | ||
| 442 | } | ||
| 443 | |||
| 444 | std::size_t index = 0; | ||
| 445 | for (std::size_t i = 0; i < finger_count; i++) { | ||
| 446 | if (auto_pilot.state[i].attribute.end_touch) { | ||
| 447 | continue; | ||
| 448 | } | ||
| 449 | auto_pilot.state[i].attribute.raw = 0; | ||
| 450 | auto_pilot.state[index] = auto_pilot.state[i]; | ||
| 451 | index++; | ||
| 452 | } | ||
| 453 | |||
| 454 | auto_pilot.count = index; | ||
| 455 | for (std::size_t i = index; i < auto_pilot.state.size(); i++) { | ||
| 456 | auto_pilot.state[i] = {}; | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | for (std::size_t i = 0; i < static_cast<std::size_t>(current_touch_state.entry_count); i++) { | ||
| 461 | auto& state = current_touch_state.states[i]; | ||
| 462 | state.position.x = static_cast<u32>((magnification.y * static_cast<f32>(state.position.x)) + | ||
| 463 | (offset.x * static_cast<f32>(TouchSensorWidth))); | ||
| 464 | state.position.y = static_cast<u32>((magnification.y * static_cast<f32>(state.position.y)) + | ||
| 465 | (offset.x * static_cast<f32>(TouchSensorHeight))); | ||
| 466 | state.diameter_x = static_cast<u32>(magnification.x * static_cast<f32>(state.diameter_x)); | ||
| 467 | state.diameter_y = static_cast<u32>(magnification.y * static_cast<f32>(state.diameter_y)); | ||
| 468 | } | ||
| 469 | |||
| 470 | std::size_t index = 0; | ||
| 471 | for (std::size_t i = 0; i < static_cast<std::size_t>(current_touch_state.entry_count); i++) { | ||
| 472 | const auto& old_state = current_touch_state.states[i]; | ||
| 473 | auto& state = current_touch_state.states[index]; | ||
| 474 | if ((TouchSensorWidth <= old_state.position.x) || | ||
| 475 | (TouchSensorHeight <= old_state.position.y)) { | ||
| 476 | continue; | ||
| 477 | } | ||
| 478 | state = old_state; | ||
| 479 | index++; | ||
| 480 | } | ||
| 481 | current_touch_state.entry_count = static_cast<s32>(index); | ||
| 482 | |||
| 483 | SanitizeInput(current_touch_state); | ||
| 484 | |||
| 485 | std::scoped_lock lock{*input_mutex}; | ||
| 486 | if (current_touch_state.entry_count == previous_touch_state.entry_count) { | ||
| 487 | if (current_touch_state.entry_count < 1) { | ||
| 488 | return; | ||
| 489 | } | ||
| 490 | bool has_moved = false; | ||
| 491 | for (std::size_t i = 0; i < static_cast<std::size_t>(current_touch_state.entry_count); | ||
| 492 | i++) { | ||
| 493 | s32 delta_x = std::abs(static_cast<s32>(current_touch_state.states[i].position.x) - | ||
| 494 | static_cast<s32>(previous_touch_state.states[i].position.x)); | ||
| 495 | s32 delta_y = std::abs(static_cast<s32>(current_touch_state.states[i].position.y) - | ||
| 496 | static_cast<s32>(previous_touch_state.states[i].position.y)); | ||
| 497 | if (delta_x > 1 || delta_y > 1) { | ||
| 498 | has_moved = true; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | if (!has_moved) { | ||
| 502 | return; | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 506 | input_event->Signal(); | ||
| 507 | } | ||
| 508 | |||
| 509 | void TouchResource::OnTouchUpdate(s64 timestamp) { | ||
| 510 | if (global_ref_counter == 0) { | ||
| 511 | return; | ||
| 512 | } | ||
| 513 | |||
| 514 | ReadTouchInput(); | ||
| 515 | gesture_handler.SetTouchState(current_touch_state.states, current_touch_state.entry_count, | ||
| 516 | timestamp); | ||
| 517 | |||
| 518 | std::scoped_lock lock{*shared_mutex}; | ||
| 519 | |||
| 520 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 521 | const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 522 | TouchAruidData& data = aruid_data[aruid_index]; | ||
| 523 | |||
| 524 | if (applet_data == nullptr || !applet_data->flag.is_assigned) { | ||
| 525 | data = {}; | ||
| 526 | continue; | ||
| 527 | } | ||
| 528 | |||
| 529 | if (data.aruid != applet_data->aruid) { | ||
| 530 | data = {}; | ||
| 531 | data.aruid = applet_data->aruid; | ||
| 532 | } | ||
| 533 | |||
| 534 | if (gesture_ref_counter != 0) { | ||
| 535 | if (!applet_data->flag.enable_touchscreen) { | ||
| 536 | gesture_state = {}; | ||
| 537 | } | ||
| 538 | if (gesture_handler.NeedsUpdate()) { | ||
| 539 | gesture_handler.UpdateGestureState(gesture_state, timestamp); | ||
| 540 | auto& gesture_shared = applet_data->shared_memory_format->gesture; | ||
| 541 | gesture_shared.gesture_lifo.WriteNextEntry(gesture_state); | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 545 | if (touch_ref_counter != 0) { | ||
| 546 | auto touch_mode = data.finger_map.touch_mode; | ||
| 547 | if (touch_mode == Core::HID::TouchScreenModeForNx::UseSystemSetting) { | ||
| 548 | touch_mode = default_touch_screen_mode; | ||
| 549 | } | ||
| 550 | |||
| 551 | if (applet_resource->GetActiveAruid() == applet_data->aruid && | ||
| 552 | touch_mode != Core::HID::TouchScreenModeForNx::UseSystemSetting && is_initalized && | ||
| 553 | handheld_config->is_handheld_hid_enabled && touch_driver->IsRunning()) { | ||
| 554 | touch_driver->SetTouchMode(touch_mode); | ||
| 555 | } | ||
| 556 | |||
| 557 | auto& touch_shared = applet_data->shared_memory_format->touch_screen; | ||
| 558 | StorePreviousTouchState(previous_touch_state, data.finger_map, current_touch_state, | ||
| 559 | applet_data->flag.enable_touchscreen.As<bool>()); | ||
| 560 | touch_shared.touch_screen_lifo.WriteNextEntry(current_touch_state); | ||
| 561 | } | ||
| 562 | } | ||
| 563 | } | ||
| 564 | |||
| 565 | void TouchResource::SanitizeInput(TouchScreenState& state) const { | ||
| 566 | for (std::size_t i = 0; i < static_cast<std::size_t>(state.entry_count); i++) { | ||
| 567 | auto& entry = state.states[i]; | ||
| 568 | entry.position.x = | ||
| 569 | std::clamp(entry.position.x, TouchBorders, TouchSensorWidth - TouchBorders - 1); | ||
| 570 | entry.position.y = | ||
| 571 | std::clamp(entry.position.y, TouchBorders, TouchSensorHeight - TouchBorders - 1); | ||
| 572 | entry.diameter_x = std::clamp(entry.diameter_x, 0u, TouchSensorWidth - MaxTouchDiameter); | ||
| 573 | entry.diameter_y = std::clamp(entry.diameter_y, 0u, TouchSensorHeight - MaxTouchDiameter); | ||
| 574 | entry.rotation_angle = | ||
| 575 | std::clamp(entry.rotation_angle, -MaxRotationAngle, MaxRotationAngle); | ||
| 576 | } | ||
| 577 | } | ||
| 578 | |||
| 579 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.h b/src/hid_core/resources/touch_screen/touch_screen_resource.h new file mode 100644 index 000000000..095cddd76 --- /dev/null +++ b/src/hid_core/resources/touch_screen/touch_screen_resource.h | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/point.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | #include "hid_core/hid_types.h" | ||
| 13 | #include "hid_core/resources/touch_screen/gesture_handler.h" | ||
| 14 | #include "hid_core/resources/touch_screen/touch_types.h" | ||
| 15 | |||
| 16 | namespace Core { | ||
| 17 | class System; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Core::Timing { | ||
| 21 | struct EventType; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace Kernel { | ||
| 25 | class KEvent; | ||
| 26 | } // namespace Kernel | ||
| 27 | |||
| 28 | namespace Service::Set { | ||
| 29 | class ISystemSettingsServer; | ||
| 30 | } | ||
| 31 | |||
| 32 | namespace Service::HID { | ||
| 33 | class AppletResource; | ||
| 34 | class TouchSharedMemoryManager; | ||
| 35 | class TouchDriver; | ||
| 36 | struct HandheldConfig; | ||
| 37 | |||
| 38 | class TouchResource { | ||
| 39 | public: | ||
| 40 | TouchResource(Core::System& system_); | ||
| 41 | ~TouchResource(); | ||
| 42 | |||
| 43 | Result ActivateTouch(); | ||
| 44 | Result ActivateTouch(u64 aruid); | ||
| 45 | |||
| 46 | Result ActivateGesture(); | ||
| 47 | Result ActivateGesture(u64 aruid, u32 basic_gesture_id); | ||
| 48 | |||
| 49 | Result DeactivateTouch(); | ||
| 50 | Result DeactivateGesture(); | ||
| 51 | |||
| 52 | bool IsTouchActive() const; | ||
| 53 | bool IsGestureActive() const; | ||
| 54 | |||
| 55 | void SetTouchDriver(std::shared_ptr<TouchDriver> driver); | ||
| 56 | void SetAppletResource(std::shared_ptr<AppletResource> shared, std::recursive_mutex* mutex); | ||
| 57 | void SetInputEvent(Kernel::KEvent* event, std::mutex* mutex); | ||
| 58 | void SetHandheldConfig(std::shared_ptr<HandheldConfig> config); | ||
| 59 | void SetTimerEvent(std::shared_ptr<Core::Timing::EventType> event); | ||
| 60 | |||
| 61 | Result SetTouchScreenAutoPilotState(const AutoPilotState& auto_pilot_state); | ||
| 62 | Result UnsetTouchScreenAutoPilotState(); | ||
| 63 | |||
| 64 | Result RequestNextTouchInput(); | ||
| 65 | Result RequestNextDummyInput(); | ||
| 66 | |||
| 67 | Result ProcessTouchScreenAutoTune(); | ||
| 68 | void SetTouchScreenMagnification(f32 point1_x, f32 point1_y, f32 point2_x, f32 point2_y); | ||
| 69 | Result SetTouchScreenResolution(u32 width, u32 height, u64 aruid); | ||
| 70 | |||
| 71 | Result SetTouchScreenConfiguration( | ||
| 72 | const Core::HID::TouchScreenConfigurationForNx& touch_configuration, u64 aruid); | ||
| 73 | Result GetTouchScreenConfiguration( | ||
| 74 | Core::HID::TouchScreenConfigurationForNx& out_touch_configuration, u64 aruid) const; | ||
| 75 | |||
| 76 | Result SetTouchScreenDefaultConfiguration( | ||
| 77 | const Core::HID::TouchScreenConfigurationForNx& touch_configuration); | ||
| 78 | Result GetTouchScreenDefaultConfiguration( | ||
| 79 | Core::HID::TouchScreenConfigurationForNx& out_touch_configuration) const; | ||
| 80 | |||
| 81 | void OnTouchUpdate(s64 timestamp); | ||
| 82 | |||
| 83 | private: | ||
| 84 | Result Finalize(); | ||
| 85 | |||
| 86 | void StorePreviousTouchState(TouchScreenState& out_previous_touch, | ||
| 87 | TouchFingerMap& out_finger_map, | ||
| 88 | const TouchScreenState& current_touch, | ||
| 89 | bool is_touch_enabled) const; | ||
| 90 | void ReadTouchInput(); | ||
| 91 | |||
| 92 | void SanitizeInput(TouchScreenState& state) const; | ||
| 93 | |||
| 94 | s32 global_ref_counter{}; | ||
| 95 | s32 gesture_ref_counter{}; | ||
| 96 | s32 touch_ref_counter{}; | ||
| 97 | bool is_initalized{}; | ||
| 98 | u64 sample_number{}; | ||
| 99 | |||
| 100 | // External resources | ||
| 101 | std::shared_ptr<Core::Timing::EventType> timer_event{nullptr}; | ||
| 102 | std::shared_ptr<TouchDriver> touch_driver{nullptr}; | ||
| 103 | std::shared_ptr<AppletResource> applet_resource{nullptr}; | ||
| 104 | std::recursive_mutex* shared_mutex{nullptr}; | ||
| 105 | std::shared_ptr<HandheldConfig> handheld_config{nullptr}; | ||
| 106 | Kernel::KEvent* input_event{nullptr}; | ||
| 107 | std::mutex* input_mutex{nullptr}; | ||
| 108 | |||
| 109 | // Internal state | ||
| 110 | TouchScreenState current_touch_state{}; | ||
| 111 | TouchScreenState previous_touch_state{}; | ||
| 112 | GestureState gesture_state{}; | ||
| 113 | bool is_auto_pilot_initialized{}; | ||
| 114 | AutoPilotState auto_pilot{}; | ||
| 115 | GestureHandler gesture_handler{}; | ||
| 116 | std::array<TouchAruidData, 0x20> aruid_data{}; | ||
| 117 | Common::Point<f32> magnification{1.0f, 1.0f}; | ||
| 118 | Common::Point<f32> offset{0.0f, 0.0f}; | ||
| 119 | Core::HID::TouchScreenModeForNx default_touch_screen_mode{ | ||
| 120 | Core::HID::TouchScreenModeForNx::Finger}; | ||
| 121 | |||
| 122 | Core::System& system; | ||
| 123 | std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; | ||
| 124 | }; | ||
| 125 | |||
| 126 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/touch_screen/touch_types.h b/src/hid_core/resources/touch_screen/touch_types.h index 97ee847da..362088939 100644 --- a/src/hid_core/resources/touch_screen/touch_types.h +++ b/src/hid_core/resources/touch_screen/touch_types.h | |||
| @@ -13,8 +13,20 @@ | |||
| 13 | #include "hid_core/hid_types.h" | 13 | #include "hid_core/hid_types.h" |
| 14 | 14 | ||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | static constexpr std::size_t MAX_FINGERS = 16; | 16 | constexpr std::size_t MaxFingers = 16; |
| 17 | static constexpr size_t MAX_POINTS = 4; | 17 | constexpr std::size_t MaxPoints = 4; |
| 18 | constexpr u32 TouchSensorWidth = 1280; | ||
| 19 | constexpr u32 TouchSensorHeight = 720; | ||
| 20 | constexpr s32 MaxRotationAngle = 270; | ||
| 21 | constexpr u32 MaxTouchDiameter = 30; | ||
| 22 | constexpr u32 TouchBorders = 15; | ||
| 23 | |||
| 24 | // HW is around 700, value is set to 400 to make it easier to trigger with mouse | ||
| 25 | constexpr f32 SwipeThreshold = 400.0f; // Threshold in pixels/s | ||
| 26 | constexpr f32 AngleThreshold = 0.015f; // Threshold in radians | ||
| 27 | constexpr f32 PinchThreshold = 0.5f; // Threshold in pixels | ||
| 28 | constexpr f32 PressDelay = 0.5f; // Time in seconds | ||
| 29 | constexpr f32 DoubleTapDelay = 0.35f; // Time in seconds | ||
| 18 | 30 | ||
| 19 | // This is nn::hid::GestureType | 31 | // This is nn::hid::GestureType |
| 20 | enum class GestureType : u32 { | 32 | enum class GestureType : u32 { |
| @@ -28,6 +40,7 @@ enum class GestureType : u32 { | |||
| 28 | Swipe, // Fast press movement and release of a single point | 40 | Swipe, // Fast press movement and release of a single point |
| 29 | Pinch, // All points moving away/closer to the midpoint | 41 | Pinch, // All points moving away/closer to the midpoint |
| 30 | Rotate, // All points rotating from the midpoint | 42 | Rotate, // All points rotating from the midpoint |
| 43 | GestureTypeMax = Rotate, | ||
| 31 | }; | 44 | }; |
| 32 | 45 | ||
| 33 | // This is nn::hid::GestureDirection | 46 | // This is nn::hid::GestureDirection |
| @@ -69,7 +82,7 @@ struct GestureState { | |||
| 69 | static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); | 82 | static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); |
| 70 | 83 | ||
| 71 | struct GestureProperties { | 84 | struct GestureProperties { |
| 72 | std::array<Common::Point<s32>, MAX_POINTS> points{}; | 85 | std::array<Common::Point<s32>, MaxPoints> points{}; |
| 73 | std::size_t active_points{}; | 86 | std::size_t active_points{}; |
| 74 | Common::Point<s32> mid_point{}; | 87 | Common::Point<s32> mid_point{}; |
| 75 | s64 detection_count{}; | 88 | s64 detection_count{}; |
| @@ -78,13 +91,53 @@ struct GestureProperties { | |||
| 78 | f32 angle{}; | 91 | f32 angle{}; |
| 79 | }; | 92 | }; |
| 80 | 93 | ||
| 94 | // This is nn::hid::TouchState | ||
| 95 | struct TouchState { | ||
| 96 | u64 delta_time{}; | ||
| 97 | Core::HID::TouchAttribute attribute{}; | ||
| 98 | u32 finger{}; | ||
| 99 | Common::Point<u32> position{}; | ||
| 100 | u32 diameter_x{}; | ||
| 101 | u32 diameter_y{}; | ||
| 102 | s32 rotation_angle{}; | ||
| 103 | }; | ||
| 104 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); | ||
| 105 | |||
| 81 | // This is nn::hid::TouchScreenState | 106 | // This is nn::hid::TouchScreenState |
| 82 | struct TouchScreenState { | 107 | struct TouchScreenState { |
| 83 | s64 sampling_number{}; | 108 | s64 sampling_number{}; |
| 84 | s32 entry_count{}; | 109 | s32 entry_count{}; |
| 85 | INSERT_PADDING_BYTES(4); // Reserved | 110 | INSERT_PADDING_BYTES(4); // Reserved |
| 86 | std::array<Core::HID::TouchState, MAX_FINGERS> states{}; | 111 | std::array<TouchState, MaxFingers> states{}; |
| 87 | }; | 112 | }; |
| 88 | static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); | 113 | static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); |
| 89 | 114 | ||
| 115 | struct TouchFingerMap { | ||
| 116 | s32 finger_count{}; | ||
| 117 | Core::HID::TouchScreenModeForNx touch_mode; | ||
| 118 | INSERT_PADDING_BYTES(3); | ||
| 119 | std::array<u32, MaxFingers> finger_ids{}; | ||
| 120 | }; | ||
| 121 | static_assert(sizeof(TouchFingerMap) == 0x48, "TouchFingerMap is an invalid size"); | ||
| 122 | |||
| 123 | struct TouchAruidData { | ||
| 124 | u64 aruid; | ||
| 125 | u32 basic_gesture_id; | ||
| 126 | u64 used_1; | ||
| 127 | u64 used_2; | ||
| 128 | u64 used_3; | ||
| 129 | u64 used_4; | ||
| 130 | GestureType gesture_type; | ||
| 131 | u16 resolution_width; | ||
| 132 | u16 resolution_height; | ||
| 133 | TouchFingerMap finger_map; | ||
| 134 | }; | ||
| 135 | static_assert(sizeof(TouchAruidData) == 0x80, "TouchAruidData is an invalid size"); | ||
| 136 | |||
| 137 | struct AutoPilotState { | ||
| 138 | u64 count; | ||
| 139 | std::array<TouchState, 16> state; | ||
| 140 | }; | ||
| 141 | static_assert(sizeof(AutoPilotState) == 0x288, "AutoPilotState is an invalid size"); | ||
| 142 | |||
| 90 | } // namespace Service::HID | 143 | } // namespace Service::HID |