summaryrefslogtreecommitdiff
path: root/src/core/hid/emulated_controller.cpp
diff options
context:
space:
mode:
authorGravatar liamwhite2023-01-24 09:29:37 -0500
committerGravatar GitHub2023-01-24 09:29:37 -0500
commita68af583ea378b48e2ed5a19f519a815ba89e40f (patch)
tree2983c14a7d4bc2797259c7d97462a439bec629f3 /src/core/hid/emulated_controller.cpp
parentMerge pull request #9555 from abouvier/catch2-update (diff)
parentcore: hid: Make use of SCOPE_EXIT and SCOPE_GUARD where applicable (diff)
downloadyuzu-a68af583ea378b48e2ed5a19f519a815ba89e40f.tar.gz
yuzu-a68af583ea378b48e2ed5a19f519a815ba89e40f.tar.xz
yuzu-a68af583ea378b48e2ed5a19f519a815ba89e40f.zip
Merge pull request #9492 from german77/joycon_release
Input_common: Implement custom joycon driver v2
Diffstat (limited to 'src/core/hid/emulated_controller.cpp')
-rw-r--r--src/core/hid/emulated_controller.cpp298
1 files changed, 217 insertions, 81 deletions
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index a959c9db9..6e9812e6e 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm> 4#include <algorithm>
5#include <common/scope_exit.h>
5 6
6#include "common/polyfill_ranges.h" 7#include "common/polyfill_ranges.h"
7#include "common/thread.h" 8#include "common/thread.h"
@@ -94,6 +95,7 @@ void EmulatedController::ReloadFromSettings() {
94 motion_params[index] = Common::ParamPackage(player.motions[index]); 95 motion_params[index] = Common::ParamPackage(player.motions[index]);
95 } 96 }
96 97
98 controller.color_values = {};
97 controller.colors_state.fullkey = { 99 controller.colors_state.fullkey = {
98 .body = GetNpadColor(player.body_color_left), 100 .body = GetNpadColor(player.body_color_left),
99 .button = GetNpadColor(player.button_color_left), 101 .button = GetNpadColor(player.button_color_left),
@@ -107,6 +109,8 @@ void EmulatedController::ReloadFromSettings() {
107 .button = GetNpadColor(player.button_color_right), 109 .button = GetNpadColor(player.button_color_right),
108 }; 110 };
109 111
112 ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs);
113
110 // Other or debug controller should always be a pro controller 114 // Other or debug controller should always be a pro controller
111 if (npad_id_type != NpadIdType::Other) { 115 if (npad_id_type != NpadIdType::Other) {
112 SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); 116 SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
@@ -133,18 +137,28 @@ void EmulatedController::LoadDevices() {
133 trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; 137 trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
134 trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; 138 trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
135 139
140 color_params[LeftIndex] = left_joycon;
141 color_params[RightIndex] = right_joycon;
142 color_params[LeftIndex].Set("color", true);
143 color_params[RightIndex].Set("color", true);
144
136 battery_params[LeftIndex] = left_joycon; 145 battery_params[LeftIndex] = left_joycon;
137 battery_params[RightIndex] = right_joycon; 146 battery_params[RightIndex] = right_joycon;
138 battery_params[LeftIndex].Set("battery", true); 147 battery_params[LeftIndex].Set("battery", true);
139 battery_params[RightIndex].Set("battery", true); 148 battery_params[RightIndex].Set("battery", true);
140 149
141 camera_params = Common::ParamPackage{"engine:camera,camera:1"}; 150 camera_params[0] = right_joycon;
142 nfc_params = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; 151 camera_params[0].Set("camera", true);
152 camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
153 ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
154 nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
155 nfc_params[1] = right_joycon;
156 nfc_params[1].Set("nfc", true);
143 157
144 output_params[LeftIndex] = left_joycon; 158 output_params[LeftIndex] = left_joycon;
145 output_params[RightIndex] = right_joycon; 159 output_params[RightIndex] = right_joycon;
146 output_params[2] = camera_params; 160 output_params[2] = camera_params[1];
147 output_params[3] = nfc_params; 161 output_params[3] = nfc_params[0];
148 output_params[LeftIndex].Set("output", true); 162 output_params[LeftIndex].Set("output", true);
149 output_params[RightIndex].Set("output", true); 163 output_params[RightIndex].Set("output", true);
150 output_params[2].Set("output", true); 164 output_params[2].Set("output", true);
@@ -160,8 +174,11 @@ void EmulatedController::LoadDevices() {
160 Common::Input::CreateInputDevice); 174 Common::Input::CreateInputDevice);
161 std::ranges::transform(battery_params, battery_devices.begin(), 175 std::ranges::transform(battery_params, battery_devices.begin(),
162 Common::Input::CreateInputDevice); 176 Common::Input::CreateInputDevice);
163 camera_devices = Common::Input::CreateInputDevice(camera_params); 177 std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice);
164 nfc_devices = Common::Input::CreateInputDevice(nfc_params); 178 std::ranges::transform(camera_params, camera_devices.begin(), Common::Input::CreateInputDevice);
179 std::ranges::transform(ring_params, ring_analog_devices.begin(),
180 Common::Input::CreateInputDevice);
181 std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice);
165 std::ranges::transform(output_params, output_devices.begin(), 182 std::ranges::transform(output_params, output_devices.begin(),
166 Common::Input::CreateOutputDevice); 183 Common::Input::CreateOutputDevice);
167 184
@@ -323,6 +340,19 @@ void EmulatedController::ReloadInput() {
323 battery_devices[index]->ForceUpdate(); 340 battery_devices[index]->ForceUpdate();
324 } 341 }
325 342
343 for (std::size_t index = 0; index < color_devices.size(); ++index) {
344 if (!color_devices[index]) {
345 continue;
346 }
347 color_devices[index]->SetCallback({
348 .on_change =
349 [this, index](const Common::Input::CallbackStatus& callback) {
350 SetColors(callback, index);
351 },
352 });
353 color_devices[index]->ForceUpdate();
354 }
355
326 for (std::size_t index = 0; index < motion_devices.size(); ++index) { 356 for (std::size_t index = 0; index < motion_devices.size(); ++index) {
327 if (!motion_devices[index]) { 357 if (!motion_devices[index]) {
328 continue; 358 continue;
@@ -336,22 +366,37 @@ void EmulatedController::ReloadInput() {
336 motion_devices[index]->ForceUpdate(); 366 motion_devices[index]->ForceUpdate();
337 } 367 }
338 368
339 if (camera_devices) { 369 for (std::size_t index = 0; index < camera_devices.size(); ++index) {
340 camera_devices->SetCallback({ 370 if (!camera_devices[index]) {
371 continue;
372 }
373 camera_devices[index]->SetCallback({
341 .on_change = 374 .on_change =
342 [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); }, 375 [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); },
343 }); 376 });
344 camera_devices->ForceUpdate(); 377 camera_devices[index]->ForceUpdate();
345 } 378 }
346 379
347 if (nfc_devices) { 380 for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) {
348 if (npad_id_type == NpadIdType::Handheld || npad_id_type == NpadIdType::Player1) { 381 if (!ring_analog_devices[index]) {
349 nfc_devices->SetCallback({ 382 continue;
350 .on_change =
351 [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); },
352 });
353 nfc_devices->ForceUpdate();
354 } 383 }
384 ring_analog_devices[index]->SetCallback({
385 .on_change =
386 [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); },
387 });
388 ring_analog_devices[index]->ForceUpdate();
389 }
390
391 for (std::size_t index = 0; index < nfc_devices.size(); ++index) {
392 if (!nfc_devices[index]) {
393 continue;
394 }
395 nfc_devices[index]->SetCallback({
396 .on_change =
397 [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); },
398 });
399 nfc_devices[index]->ForceUpdate();
355 } 400 }
356 401
357 // Register TAS devices. No need to force update 402 // Register TAS devices. No need to force update
@@ -421,6 +466,9 @@ void EmulatedController::UnloadInput() {
421 for (auto& battery : battery_devices) { 466 for (auto& battery : battery_devices) {
422 battery.reset(); 467 battery.reset();
423 } 468 }
469 for (auto& color : color_devices) {
470 color.reset();
471 }
424 for (auto& output : output_devices) { 472 for (auto& output : output_devices) {
425 output.reset(); 473 output.reset();
426 } 474 }
@@ -436,8 +484,15 @@ void EmulatedController::UnloadInput() {
436 for (auto& stick : virtual_stick_devices) { 484 for (auto& stick : virtual_stick_devices) {
437 stick.reset(); 485 stick.reset();
438 } 486 }
439 camera_devices.reset(); 487 for (auto& camera : camera_devices) {
440 nfc_devices.reset(); 488 camera.reset();
489 }
490 for (auto& ring : ring_analog_devices) {
491 ring.reset();
492 }
493 for (auto& nfc : nfc_devices) {
494 nfc.reset();
495 }
441} 496}
442 497
443void EmulatedController::EnableConfiguration() { 498void EmulatedController::EnableConfiguration() {
@@ -449,6 +504,11 @@ void EmulatedController::EnableConfiguration() {
449void EmulatedController::DisableConfiguration() { 504void EmulatedController::DisableConfiguration() {
450 is_configuring = false; 505 is_configuring = false;
451 506
507 // Get Joycon colors before turning on the controller
508 for (const auto& color_device : color_devices) {
509 color_device->ForceUpdate();
510 }
511
452 // Apply temporary npad type to the real controller 512 // Apply temporary npad type to the real controller
453 if (tmp_npad_type != npad_type) { 513 if (tmp_npad_type != npad_type) {
454 if (is_connected) { 514 if (is_connected) {
@@ -502,6 +562,9 @@ void EmulatedController::SaveCurrentConfig() {
502 for (std::size_t index = 0; index < player.motions.size(); ++index) { 562 for (std::size_t index = 0; index < player.motions.size(); ++index) {
503 player.motions[index] = motion_params[index].Serialize(); 563 player.motions[index] = motion_params[index].Serialize();
504 } 564 }
565 if (npad_id_type == NpadIdType::Player1) {
566 Settings::values.ringcon_analogs = ring_params[0].Serialize();
567 }
505} 568}
506 569
507void EmulatedController::RestoreConfig() { 570void EmulatedController::RestoreConfig() {
@@ -773,17 +836,21 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
773 if (index >= controller.stick_values.size()) { 836 if (index >= controller.stick_values.size()) {
774 return; 837 return;
775 } 838 }
776 std::unique_lock lock{mutex}; 839 auto trigger_guard =
840 SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
841 std::scoped_lock lock{mutex};
777 const auto stick_value = TransformToStick(callback); 842 const auto stick_value = TransformToStick(callback);
778 843
779 // Only read stick values that have the same uuid or are over the threshold to avoid flapping 844 // Only read stick values that have the same uuid or are over the threshold to avoid flapping
780 if (controller.stick_values[index].uuid != uuid) { 845 if (controller.stick_values[index].uuid != uuid) {
781 const bool is_tas = uuid == TAS_UUID; 846 const bool is_tas = uuid == TAS_UUID;
782 if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) { 847 if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
848 trigger_guard.Cancel();
783 return; 849 return;
784 } 850 }
785 if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left && 851 if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
786 !stick_value.right) { 852 !stick_value.right) {
853 trigger_guard.Cancel();
787 return; 854 return;
788 } 855 }
789 } 856 }
@@ -794,8 +861,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
794 if (is_configuring) { 861 if (is_configuring) {
795 controller.analog_stick_state.left = {}; 862 controller.analog_stick_state.left = {};
796 controller.analog_stick_state.right = {}; 863 controller.analog_stick_state.right = {};
797 lock.unlock();
798 TriggerOnChange(ControllerTriggerType::Stick, false);
799 return; 864 return;
800 } 865 }
801 866
@@ -827,9 +892,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
827 controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); 892 controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
828 break; 893 break;
829 } 894 }
830
831 lock.unlock();
832 TriggerOnChange(ControllerTriggerType::Stick, true);
833} 895}
834 896
835void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, 897void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
@@ -837,7 +899,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
837 if (index >= controller.trigger_values.size()) { 899 if (index >= controller.trigger_values.size()) {
838 return; 900 return;
839 } 901 }
840 std::unique_lock lock{mutex}; 902 auto trigger_guard =
903 SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
904 std::scoped_lock lock{mutex};
841 const auto trigger_value = TransformToTrigger(callback); 905 const auto trigger_value = TransformToTrigger(callback);
842 906
843 // Only read trigger values that have the same uuid or are pressed once 907 // Only read trigger values that have the same uuid or are pressed once
@@ -853,13 +917,12 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
853 if (is_configuring) { 917 if (is_configuring) {
854 controller.gc_trigger_state.left = 0; 918 controller.gc_trigger_state.left = 0;
855 controller.gc_trigger_state.right = 0; 919 controller.gc_trigger_state.right = 0;
856 lock.unlock();
857 TriggerOnChange(ControllerTriggerType::Trigger, false);
858 return; 920 return;
859 } 921 }
860 922
861 // Only GC controllers have analog triggers 923 // Only GC controllers have analog triggers
862 if (npad_type != NpadStyleIndex::GameCube) { 924 if (npad_type != NpadStyleIndex::GameCube) {
925 trigger_guard.Cancel();
863 return; 926 return;
864 } 927 }
865 928
@@ -876,9 +939,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
876 controller.npad_button_state.zr.Assign(trigger.pressed.value); 939 controller.npad_button_state.zr.Assign(trigger.pressed.value);
877 break; 940 break;
878 } 941 }
879
880 lock.unlock();
881 TriggerOnChange(ControllerTriggerType::Trigger, true);
882} 942}
883 943
884void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, 944void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
@@ -886,7 +946,8 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
886 if (index >= controller.motion_values.size()) { 946 if (index >= controller.motion_values.size()) {
887 return; 947 return;
888 } 948 }
889 std::unique_lock lock{mutex}; 949 SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); });
950 std::scoped_lock lock{mutex};
890 auto& raw_status = controller.motion_values[index].raw_status; 951 auto& raw_status = controller.motion_values[index].raw_status;
891 auto& emulated = controller.motion_values[index].emulated; 952 auto& emulated = controller.motion_values[index].emulated;
892 953
@@ -907,8 +968,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
907 force_update_motion = raw_status.force_update; 968 force_update_motion = raw_status.force_update;
908 969
909 if (is_configuring) { 970 if (is_configuring) {
910 lock.unlock();
911 TriggerOnChange(ControllerTriggerType::Motion, false);
912 return; 971 return;
913 } 972 }
914 973
@@ -918,9 +977,56 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
918 motion.rotation = emulated.GetRotations(); 977 motion.rotation = emulated.GetRotations();
919 motion.orientation = emulated.GetOrientation(); 978 motion.orientation = emulated.GetOrientation();
920 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); 979 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
980}
921 981
922 lock.unlock(); 982void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
923 TriggerOnChange(ControllerTriggerType::Motion, true); 983 std::size_t index) {
984 if (index >= controller.color_values.size()) {
985 return;
986 }
987 auto trigger_guard =
988 SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); });
989 std::scoped_lock lock{mutex};
990 controller.color_values[index] = TransformToColor(callback);
991
992 if (is_configuring) {
993 return;
994 }
995
996 if (controller.color_values[index].body == 0) {
997 trigger_guard.Cancel();
998 return;
999 }
1000
1001 controller.colors_state.fullkey = {
1002 .body = GetNpadColor(controller.color_values[index].body),
1003 .button = GetNpadColor(controller.color_values[index].buttons),
1004 };
1005 if (npad_type == NpadStyleIndex::ProController) {
1006 controller.colors_state.left = {
1007 .body = GetNpadColor(controller.color_values[index].left_grip),
1008 .button = GetNpadColor(controller.color_values[index].buttons),
1009 };
1010 controller.colors_state.right = {
1011 .body = GetNpadColor(controller.color_values[index].right_grip),
1012 .button = GetNpadColor(controller.color_values[index].buttons),
1013 };
1014 } else {
1015 switch (index) {
1016 case LeftIndex:
1017 controller.colors_state.left = {
1018 .body = GetNpadColor(controller.color_values[index].body),
1019 .button = GetNpadColor(controller.color_values[index].buttons),
1020 };
1021 break;
1022 case RightIndex:
1023 controller.colors_state.right = {
1024 .body = GetNpadColor(controller.color_values[index].body),
1025 .button = GetNpadColor(controller.color_values[index].buttons),
1026 };
1027 break;
1028 }
1029 }
924} 1030}
925 1031
926void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, 1032void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
@@ -928,12 +1034,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
928 if (index >= controller.battery_values.size()) { 1034 if (index >= controller.battery_values.size()) {
929 return; 1035 return;
930 } 1036 }
931 std::unique_lock lock{mutex}; 1037 SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); });
1038 std::scoped_lock lock{mutex};
932 controller.battery_values[index] = TransformToBattery(callback); 1039 controller.battery_values[index] = TransformToBattery(callback);
933 1040
934 if (is_configuring) { 1041 if (is_configuring) {
935 lock.unlock();
936 TriggerOnChange(ControllerTriggerType::Battery, false);
937 return; 1042 return;
938 } 1043 }
939 1044
@@ -989,18 +1094,14 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
989 }; 1094 };
990 break; 1095 break;
991 } 1096 }
992
993 lock.unlock();
994 TriggerOnChange(ControllerTriggerType::Battery, true);
995} 1097}
996 1098
997void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { 1099void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
998 std::unique_lock lock{mutex}; 1100 SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); });
1101 std::scoped_lock lock{mutex};
999 controller.camera_values = TransformToCamera(callback); 1102 controller.camera_values = TransformToCamera(callback);
1000 1103
1001 if (is_configuring) { 1104 if (is_configuring) {
1002 lock.unlock();
1003 TriggerOnChange(ControllerTriggerType::IrSensor, false);
1004 return; 1105 return;
1005 } 1106 }
1006 1107
@@ -1008,18 +1109,28 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback
1008 controller.camera_state.format = 1109 controller.camera_state.format =
1009 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format); 1110 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
1010 controller.camera_state.data = controller.camera_values.data; 1111 controller.camera_state.data = controller.camera_values.data;
1112}
1011 1113
1012 lock.unlock(); 1114void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
1013 TriggerOnChange(ControllerTriggerType::IrSensor, true); 1115 SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); });
1116 std::scoped_lock lock{mutex};
1117 const auto force_value = TransformToStick(callback);
1118
1119 controller.ring_analog_value = force_value.x;
1120
1121 if (is_configuring) {
1122 return;
1123 }
1124
1125 controller.ring_analog_state.force = force_value.x.value;
1014} 1126}
1015 1127
1016void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { 1128void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
1017 std::unique_lock lock{mutex}; 1129 SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); });
1130 std::scoped_lock lock{mutex};
1018 controller.nfc_values = TransformToNfc(callback); 1131 controller.nfc_values = TransformToNfc(callback);
1019 1132
1020 if (is_configuring) { 1133 if (is_configuring) {
1021 lock.unlock();
1022 TriggerOnChange(ControllerTriggerType::Nfc, false);
1023 return; 1134 return;
1024 } 1135 }
1025 1136
@@ -1027,9 +1138,6 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
1027 controller.nfc_values.state, 1138 controller.nfc_values.state,
1028 controller.nfc_values.data, 1139 controller.nfc_values.data,
1029 }; 1140 };
1030
1031 lock.unlock();
1032 TriggerOnChange(ControllerTriggerType::Nfc, true);
1033} 1141}
1034 1142
1035bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { 1143bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
@@ -1061,7 +1169,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
1061 .type = type, 1169 .type = type,
1062 }; 1170 };
1063 return output_devices[device_index]->SetVibration(status) == 1171 return output_devices[device_index]->SetVibration(status) ==
1064 Common::Input::VibrationError::None; 1172 Common::Input::DriverResult::Success;
1065} 1173}
1066 1174
1067bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { 1175bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
@@ -1083,16 +1191,32 @@ bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
1083 return output_devices[device_index]->IsVibrationEnabled(); 1191 return output_devices[device_index]->IsVibrationEnabled();
1084} 1192}
1085 1193
1086bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) { 1194Common::Input::DriverResult EmulatedController::SetPollingMode(
1087 LOG_INFO(Service_HID, "Set polling mode {}", polling_mode); 1195 EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) {
1088 auto& output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; 1196 LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index);
1197
1198 auto& left_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Left)];
1199 auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
1089 auto& nfc_output_device = output_devices[3]; 1200 auto& nfc_output_device = output_devices[3];
1090 1201
1091 const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); 1202 if (device_index == EmulatedDeviceIndex::LeftIndex) {
1092 const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode); 1203 return left_output_device->SetPollingMode(polling_mode);
1204 }
1205
1206 if (device_index == EmulatedDeviceIndex::RightIndex) {
1207 const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
1208 const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode);
1209
1210 if (virtual_nfc_result == Common::Input::DriverResult::Success) {
1211 return virtual_nfc_result;
1212 }
1213 return mapped_nfc_result;
1214 }
1093 1215
1094 return virtual_nfc_result == Common::Input::PollingError::None || 1216 left_output_device->SetPollingMode(polling_mode);
1095 mapped_nfc_result == Common::Input::PollingError::None; 1217 right_output_device->SetPollingMode(polling_mode);
1218 nfc_output_device->SetPollingMode(polling_mode);
1219 return Common::Input::DriverResult::Success;
1096} 1220}
1097 1221
1098bool EmulatedController::SetCameraFormat( 1222bool EmulatedController::SetCameraFormat(
@@ -1103,13 +1227,22 @@ bool EmulatedController::SetCameraFormat(
1103 auto& camera_output_device = output_devices[2]; 1227 auto& camera_output_device = output_devices[2];
1104 1228
1105 if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( 1229 if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
1106 camera_format)) == Common::Input::CameraError::None) { 1230 camera_format)) == Common::Input::DriverResult::Success) {
1107 return true; 1231 return true;
1108 } 1232 }
1109 1233
1110 // Fallback to Qt camera if native device doesn't have support 1234 // Fallback to Qt camera if native device doesn't have support
1111 return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( 1235 return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
1112 camera_format)) == Common::Input::CameraError::None; 1236 camera_format)) == Common::Input::DriverResult::Success;
1237}
1238
1239Common::ParamPackage EmulatedController::GetRingParam() const {
1240 return ring_params[0];
1241}
1242
1243void EmulatedController::SetRingParam(Common::ParamPackage param) {
1244 ring_params[0] = std::move(param);
1245 ReloadInput();
1113} 1246}
1114 1247
1115bool EmulatedController::HasNfc() const { 1248bool EmulatedController::HasNfc() const {
@@ -1263,39 +1396,35 @@ void EmulatedController::Connect(bool use_temporary_value) {
1263 return; 1396 return;
1264 } 1397 }
1265 1398
1266 std::unique_lock lock{mutex}; 1399 auto trigger_guard =
1400 SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
1401 std::scoped_lock lock{mutex};
1267 if (is_configuring) { 1402 if (is_configuring) {
1268 tmp_is_connected = true; 1403 tmp_is_connected = true;
1269 lock.unlock();
1270 TriggerOnChange(ControllerTriggerType::Connected, false);
1271 return; 1404 return;
1272 } 1405 }
1273 1406
1274 if (is_connected) { 1407 if (is_connected) {
1408 trigger_guard.Cancel();
1275 return; 1409 return;
1276 } 1410 }
1277 is_connected = true; 1411 is_connected = true;
1278
1279 lock.unlock();
1280 TriggerOnChange(ControllerTriggerType::Connected, true);
1281} 1412}
1282 1413
1283void EmulatedController::Disconnect() { 1414void EmulatedController::Disconnect() {
1284 std::unique_lock lock{mutex}; 1415 auto trigger_guard =
1416 SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
1417 std::scoped_lock lock{mutex};
1285 if (is_configuring) { 1418 if (is_configuring) {
1286 tmp_is_connected = false; 1419 tmp_is_connected = false;
1287 lock.unlock();
1288 TriggerOnChange(ControllerTriggerType::Disconnected, false);
1289 return; 1420 return;
1290 } 1421 }
1291 1422
1292 if (!is_connected) { 1423 if (!is_connected) {
1424 trigger_guard.Cancel();
1293 return; 1425 return;
1294 } 1426 }
1295 is_connected = false; 1427 is_connected = false;
1296
1297 lock.unlock();
1298 TriggerOnChange(ControllerTriggerType::Disconnected, true);
1299} 1428}
1300 1429
1301bool EmulatedController::IsConnected(bool get_temporary_value) const { 1430bool EmulatedController::IsConnected(bool get_temporary_value) const {
@@ -1320,19 +1449,21 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c
1320} 1449}
1321 1450
1322void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { 1451void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
1323 std::unique_lock lock{mutex}; 1452 auto trigger_guard =
1453 SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
1454 std::scoped_lock lock{mutex};
1324 1455
1325 if (is_configuring) { 1456 if (is_configuring) {
1326 if (tmp_npad_type == npad_type_) { 1457 if (tmp_npad_type == npad_type_) {
1458 trigger_guard.Cancel();
1327 return; 1459 return;
1328 } 1460 }
1329 tmp_npad_type = npad_type_; 1461 tmp_npad_type = npad_type_;
1330 lock.unlock();
1331 TriggerOnChange(ControllerTriggerType::Type, false);
1332 return; 1462 return;
1333 } 1463 }
1334 1464
1335 if (npad_type == npad_type_) { 1465 if (npad_type == npad_type_) {
1466 trigger_guard.Cancel();
1336 return; 1467 return;
1337 } 1468 }
1338 if (is_connected) { 1469 if (is_connected) {
@@ -1340,9 +1471,6 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
1340 NpadIdTypeToIndex(npad_id_type)); 1471 NpadIdTypeToIndex(npad_id_type));
1341 } 1472 }
1342 npad_type = npad_type_; 1473 npad_type = npad_type_;
1343
1344 lock.unlock();
1345 TriggerOnChange(ControllerTriggerType::Type, true);
1346} 1474}
1347 1475
1348LedPattern EmulatedController::GetLedPattern() const { 1476LedPattern EmulatedController::GetLedPattern() const {
@@ -1403,6 +1531,10 @@ CameraValues EmulatedController::GetCameraValues() const {
1403 return controller.camera_values; 1531 return controller.camera_values;
1404} 1532}
1405 1533
1534RingAnalogValue EmulatedController::GetRingSensorValues() const {
1535 return controller.ring_analog_value;
1536}
1537
1406HomeButtonState EmulatedController::GetHomeButtons() const { 1538HomeButtonState EmulatedController::GetHomeButtons() const {
1407 std::scoped_lock lock{mutex}; 1539 std::scoped_lock lock{mutex};
1408 if (is_configuring) { 1540 if (is_configuring) {
@@ -1436,7 +1568,7 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const {
1436} 1568}
1437 1569
1438AnalogSticks EmulatedController::GetSticks() const { 1570AnalogSticks EmulatedController::GetSticks() const {
1439 std::unique_lock lock{mutex}; 1571 std::scoped_lock lock{mutex};
1440 1572
1441 if (is_configuring) { 1573 if (is_configuring) {
1442 return {}; 1574 return {};
@@ -1486,6 +1618,10 @@ const CameraState& EmulatedController::GetCamera() const {
1486 return controller.camera_state; 1618 return controller.camera_state;
1487} 1619}
1488 1620
1621RingSensorForce EmulatedController::GetRingSensorForce() const {
1622 return controller.ring_analog_state;
1623}
1624
1489const NfcState& EmulatedController::GetNfc() const { 1625const NfcState& EmulatedController::GetNfc() const {
1490 std::scoped_lock lock{mutex}; 1626 std::scoped_lock lock{mutex};
1491 return controller.nfc_state; 1627 return controller.nfc_state;