summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hid/hid_types.h43
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp648
-rw-r--r--src/core/hle/service/hid/controllers/npad.h75
-rw-r--r--src/core/hle/service/hid/errors.h4
-rw-r--r--src/core/hle/service/hid/hid.cpp236
-rw-r--r--src/core/hle/service/hid/hid.h5
6 files changed, 643 insertions, 368 deletions
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 26ec1091b..9f76f9bcb 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -498,6 +498,49 @@ struct SixAxisSensorFusionParameters {
498static_assert(sizeof(SixAxisSensorFusionParameters) == 8, 498static_assert(sizeof(SixAxisSensorFusionParameters) == 8,
499 "SixAxisSensorFusionParameters is an invalid size"); 499 "SixAxisSensorFusionParameters is an invalid size");
500 500
501// This is nn::hid::server::SixAxisSensorProperties
502struct SixAxisSensorProperties {
503 union {
504 u8 raw{};
505 BitField<0, 1, u8> is_newly_assigned;
506 BitField<1, 1, u8> is_firmware_update_available;
507 };
508};
509static_assert(sizeof(SixAxisSensorProperties) == 1, "SixAxisSensorProperties is an invalid size");
510
511// This is nn::hid::SixAxisSensorCalibrationParameter
512struct SixAxisSensorCalibrationParameter {
513 std::array<u8, 0x744> unknown_data{};
514};
515static_assert(sizeof(SixAxisSensorCalibrationParameter) == 0x744,
516 "SixAxisSensorCalibrationParameter is an invalid size");
517
518// This is nn::hid::SixAxisSensorIcInformation
519struct SixAxisSensorIcInformation {
520 f32 angular_rate{2000.0f}; // dps
521 std::array<f32, 6> unknown_gyro_data1{
522 -10.0f, -10.0f, -10.0f, 10.0f, 10.0f, 10.0f,
523 }; // dps
524 std::array<f32, 9> unknown_gyro_data2{
525 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f,
526 };
527 std::array<f32, 9> unknown_gyro_data3{
528 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f,
529 };
530 f32 acceleration_range{8.0f}; // g force
531 std::array<f32, 6> unknown_accel_data1{
532 -0.0612f, -0.0612f, -0.0612f, 0.0612f, 0.0612f, 0.0612f,
533 }; // g force
534 std::array<f32, 9> unknown_accel_data2{
535 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f,
536 };
537 std::array<f32, 9> unknown_accel_data3{
538 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f,
539 };
540};
541static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8,
542 "SixAxisSensorIcInformation is an invalid size");
543
501// This is nn::hid::VibrationDeviceHandle 544// This is nn::hid::VibrationDeviceHandle
502struct VibrationDeviceHandle { 545struct VibrationDeviceHandle {
503 NpadStyleIndex npad_type{NpadStyleIndex::None}; 546 NpadStyleIndex npad_type{NpadStyleIndex::None};
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index de06e1735..1e04ee3f2 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -56,11 +56,22 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle
56 return npad_id && npad_type && device_index; 56 return npad_id && npad_type && device_index;
57} 57}
58 58
59bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) { 59ResultCode Controller_NPad::VerifyValidSixAxisSensorHandle(
60 const Core::HID::SixAxisSensorHandle& device_handle) {
60 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)); 61 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
61 const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType; 62 if (!npad_id) {
63 return InvalidNpadId;
64 }
62 const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; 65 const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
63 return npad_id && npad_type && device_index; 66 if (!device_index) {
67 return NpadDeviceIndexOutOfRange;
68 }
69 // This doesn't get validated on nnsdk
70 const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
71 if (!npad_type) {
72 return NpadInvalidHandle;
73 }
74 return ResultSuccess;
64} 75}
65 76
66Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 77Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
@@ -158,6 +169,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
158 shared_memory->system_properties.use_plus.Assign(1); 169 shared_memory->system_properties.use_plus.Assign(1);
159 shared_memory->system_properties.use_minus.Assign(1); 170 shared_memory->system_properties.use_minus.Assign(1);
160 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController; 171 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
172 shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
161 break; 173 break;
162 case Core::HID::NpadStyleIndex::Handheld: 174 case Core::HID::NpadStyleIndex::Handheld:
163 shared_memory->style_tag.handheld.Assign(1); 175 shared_memory->style_tag.handheld.Assign(1);
@@ -170,16 +182,19 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
170 shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; 182 shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
171 shared_memory->applet_nfc_xcd.applet_footer.type = 183 shared_memory->applet_nfc_xcd.applet_footer.type =
172 AppletFooterUiType::HandheldJoyConLeftJoyConRight; 184 AppletFooterUiType::HandheldJoyConLeftJoyConRight;
185 shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1);
173 break; 186 break;
174 case Core::HID::NpadStyleIndex::JoyconDual: 187 case Core::HID::NpadStyleIndex::JoyconDual:
175 shared_memory->style_tag.joycon_dual.Assign(1); 188 shared_memory->style_tag.joycon_dual.Assign(1);
176 if (controller.is_dual_left_connected) { 189 if (controller.is_dual_left_connected) {
177 shared_memory->device_type.joycon_left.Assign(1); 190 shared_memory->device_type.joycon_left.Assign(1);
178 shared_memory->system_properties.use_minus.Assign(1); 191 shared_memory->system_properties.use_minus.Assign(1);
192 shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1);
179 } 193 }
180 if (controller.is_dual_right_connected) { 194 if (controller.is_dual_right_connected) {
181 shared_memory->device_type.joycon_right.Assign(1); 195 shared_memory->device_type.joycon_right.Assign(1);
182 shared_memory->system_properties.use_plus.Assign(1); 196 shared_memory->system_properties.use_plus.Assign(1);
197 shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1);
183 } 198 }
184 shared_memory->system_properties.use_directional_buttons.Assign(1); 199 shared_memory->system_properties.use_directional_buttons.Assign(1);
185 shared_memory->system_properties.is_vertical.Assign(1); 200 shared_memory->system_properties.is_vertical.Assign(1);
@@ -198,6 +213,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
198 shared_memory->system_properties.is_horizontal.Assign(1); 213 shared_memory->system_properties.is_horizontal.Assign(1);
199 shared_memory->system_properties.use_minus.Assign(1); 214 shared_memory->system_properties.use_minus.Assign(1);
200 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; 215 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
216 shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
201 break; 217 break;
202 case Core::HID::NpadStyleIndex::JoyconRight: 218 case Core::HID::NpadStyleIndex::JoyconRight:
203 shared_memory->style_tag.joycon_right.Assign(1); 219 shared_memory->style_tag.joycon_right.Assign(1);
@@ -205,6 +221,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
205 shared_memory->system_properties.is_horizontal.Assign(1); 221 shared_memory->system_properties.is_horizontal.Assign(1);
206 shared_memory->system_properties.use_plus.Assign(1); 222 shared_memory->system_properties.use_plus.Assign(1);
207 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; 223 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
224 shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1);
208 break; 225 break;
209 case Core::HID::NpadStyleIndex::GameCube: 226 case Core::HID::NpadStyleIndex::GameCube:
210 shared_memory->style_tag.gamecube.Assign(1); 227 shared_memory->style_tag.gamecube.Assign(1);
@@ -215,6 +232,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
215 case Core::HID::NpadStyleIndex::Pokeball: 232 case Core::HID::NpadStyleIndex::Pokeball:
216 shared_memory->style_tag.palma.Assign(1); 233 shared_memory->style_tag.palma.Assign(1);
217 shared_memory->device_type.palma.Assign(1); 234 shared_memory->device_type.palma.Assign(1);
235 shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
218 break; 236 break;
219 case Core::HID::NpadStyleIndex::NES: 237 case Core::HID::NpadStyleIndex::NES:
220 shared_memory->style_tag.lark.Assign(1); 238 shared_memory->style_tag.lark.Assign(1);
@@ -582,6 +600,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
582 UNREACHABLE(); 600 UNREACHABLE();
583 break; 601 break;
584 case Core::HID::NpadStyleIndex::ProController: 602 case Core::HID::NpadStyleIndex::ProController:
603 case Core::HID::NpadStyleIndex::Pokeball:
585 set_motion_state(sixaxis_fullkey_state, motion_state[0]); 604 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
586 break; 605 break;
587 case Core::HID::NpadStyleIndex::Handheld: 606 case Core::HID::NpadStyleIndex::Handheld:
@@ -672,6 +691,12 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
672} 691}
673 692
674void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { 693void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
694 if (joy_hold_type != NpadJoyHoldType::Horizontal &&
695 joy_hold_type != NpadJoyHoldType::Vertical) {
696 LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}",
697 joy_hold_type);
698 return;
699 }
675 hold_type = joy_hold_type; 700 hold_type = joy_hold_type;
676} 701}
677 702
@@ -695,11 +720,12 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
695 return communication_mode; 720 return communication_mode;
696} 721}
697 722
698void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, 723ResultCode Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
699 NpadJoyAssignmentMode assignment_mode) { 724 NpadJoyDeviceType npad_device_type,
725 NpadJoyAssignmentMode assignment_mode) {
700 if (!IsNpadIdValid(npad_id)) { 726 if (!IsNpadIdValid(npad_id)) {
701 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 727 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
702 return; 728 return InvalidNpadId;
703 } 729 }
704 730
705 auto& controller = GetControllerFromNpadIdType(npad_id); 731 auto& controller = GetControllerFromNpadIdType(npad_id);
@@ -708,7 +734,7 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
708 } 734 }
709 735
710 if (!controller.device->IsConnected()) { 736 if (!controller.device->IsConnected()) {
711 return; 737 return ResultSuccess;
712 } 738 }
713 739
714 if (assignment_mode == NpadJoyAssignmentMode::Dual) { 740 if (assignment_mode == NpadJoyAssignmentMode::Dual) {
@@ -717,34 +743,34 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
717 controller.is_dual_left_connected = true; 743 controller.is_dual_left_connected = true;
718 controller.is_dual_right_connected = false; 744 controller.is_dual_right_connected = false;
719 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); 745 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
720 return; 746 return ResultSuccess;
721 } 747 }
722 if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { 748 if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
723 DisconnectNpad(npad_id); 749 DisconnectNpad(npad_id);
724 controller.is_dual_left_connected = false; 750 controller.is_dual_left_connected = false;
725 controller.is_dual_right_connected = true; 751 controller.is_dual_right_connected = true;
726 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); 752 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
727 return; 753 return ResultSuccess;
728 } 754 }
729 return; 755 return ResultSuccess;
730 } 756 }
731 757
732 // This is for NpadJoyAssignmentMode::Single 758 // This is for NpadJoyAssignmentMode::Single
733 759
734 // Only JoyconDual get affected by this function 760 // Only JoyconDual get affected by this function
735 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { 761 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
736 return; 762 return ResultSuccess;
737 } 763 }
738 764
739 if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { 765 if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
740 DisconnectNpad(npad_id); 766 DisconnectNpad(npad_id);
741 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); 767 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
742 return; 768 return ResultSuccess;
743 } 769 }
744 if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { 770 if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
745 DisconnectNpad(npad_id); 771 DisconnectNpad(npad_id);
746 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); 772 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
747 return; 773 return ResultSuccess;
748 } 774 }
749 775
750 // We have two controllers connected to the same npad_id we need to split them 776 // We have two controllers connected to the same npad_id we need to split them
@@ -762,6 +788,7 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
762 controller_2.is_dual_right_connected = false; 788 controller_2.is_dual_right_connected = false;
763 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); 789 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
764 } 790 }
791 return ResultSuccess;
765} 792}
766 793
767bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, 794bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
@@ -957,10 +984,10 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
957 InitNewlyAddedController(npad_id); 984 InitNewlyAddedController(npad_id);
958} 985}
959 986
960void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { 987ResultCode Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
961 if (!IsNpadIdValid(npad_id)) { 988 if (!IsNpadIdValid(npad_id)) {
962 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 989 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
963 return; 990 return InvalidNpadId;
964 } 991 }
965 992
966 LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); 993 LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
@@ -977,6 +1004,12 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
977 shared_memory->device_type.raw = 0; 1004 shared_memory->device_type.raw = 0;
978 shared_memory->system_properties.raw = 0; 1005 shared_memory->system_properties.raw = 0;
979 shared_memory->button_properties.raw = 0; 1006 shared_memory->button_properties.raw = 0;
1007 shared_memory->sixaxis_fullkey_properties.raw = 0;
1008 shared_memory->sixaxis_handheld_properties.raw = 0;
1009 shared_memory->sixaxis_dual_left_properties.raw = 0;
1010 shared_memory->sixaxis_dual_right_properties.raw = 0;
1011 shared_memory->sixaxis_left_properties.raw = 0;
1012 shared_memory->sixaxis_right_properties.raw = 0;
980 shared_memory->battery_level_dual = 0; 1013 shared_memory->battery_level_dual = 0;
981 shared_memory->battery_level_left = 0; 1014 shared_memory->battery_level_left = 0;
982 shared_memory->battery_level_right = 0; 1015 shared_memory->battery_level_right = 0;
@@ -997,346 +1030,268 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
997 controller.device->Disconnect(); 1030 controller.device->Disconnect();
998 SignalStyleSetChangedEvent(npad_id); 1031 SignalStyleSetChangedEvent(npad_id);
999 WriteEmptyEntry(shared_memory); 1032 WriteEmptyEntry(shared_memory);
1033 return ResultSuccess;
1000} 1034}
1001 1035ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(
1002ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, 1036 const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) {
1003 GyroscopeZeroDriftMode drift_mode) { 1037 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1004 if (!IsDeviceHandleValid(sixaxis_handle)) { 1038 if (is_valid.IsError()) {
1005 LOG_ERROR(Service_HID, "Invalid handle"); 1039 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1006 return NpadInvalidHandle; 1040 return is_valid;
1007 } 1041 }
1008 1042
1009 auto& controller = GetControllerFromHandle(sixaxis_handle); 1043 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1010 switch (sixaxis_handle.npad_type) { 1044 sixaxis.gyroscope_zero_drift_mode = drift_mode;
1011 case Core::HID::NpadStyleIndex::ProController:
1012 controller.sixaxis_fullkey.gyroscope_zero_drift_mode = drift_mode;
1013 break;
1014 case Core::HID::NpadStyleIndex::Handheld:
1015 controller.sixaxis_handheld.gyroscope_zero_drift_mode = drift_mode;
1016 break;
1017 case Core::HID::NpadStyleIndex::JoyconDual:
1018 case Core::HID::NpadStyleIndex::GameCube:
1019 case Core::HID::NpadStyleIndex::Pokeball:
1020 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1021 controller.sixaxis_dual_left.gyroscope_zero_drift_mode = drift_mode;
1022 break;
1023 }
1024 controller.sixaxis_dual_right.gyroscope_zero_drift_mode = drift_mode;
1025 break;
1026 case Core::HID::NpadStyleIndex::JoyconLeft:
1027 controller.sixaxis_left.gyroscope_zero_drift_mode = drift_mode;
1028 break;
1029 case Core::HID::NpadStyleIndex::JoyconRight:
1030 controller.sixaxis_right.gyroscope_zero_drift_mode = drift_mode;
1031 break;
1032 default:
1033 LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
1034 return NpadInvalidHandle;
1035 }
1036 1045
1037 return ResultSuccess; 1046 return ResultSuccess;
1038} 1047}
1039 1048
1040ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, 1049ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(
1041 GyroscopeZeroDriftMode& drift_mode) const { 1050 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1042 if (!IsDeviceHandleValid(sixaxis_handle)) { 1051 GyroscopeZeroDriftMode& drift_mode) const {
1043 LOG_ERROR(Service_HID, "Invalid handle"); 1052 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1044 return NpadInvalidHandle; 1053 if (is_valid.IsError()) {
1054 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1055 return is_valid;
1045 } 1056 }
1046 1057
1047 auto& controller = GetControllerFromHandle(sixaxis_handle); 1058 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1048 switch (sixaxis_handle.npad_type) { 1059 drift_mode = sixaxis.gyroscope_zero_drift_mode;
1049 case Core::HID::NpadStyleIndex::ProController:
1050 drift_mode = controller.sixaxis_fullkey.gyroscope_zero_drift_mode;
1051 break;
1052 case Core::HID::NpadStyleIndex::Handheld:
1053 drift_mode = controller.sixaxis_handheld.gyroscope_zero_drift_mode;
1054 break;
1055 case Core::HID::NpadStyleIndex::JoyconDual:
1056 case Core::HID::NpadStyleIndex::GameCube:
1057 case Core::HID::NpadStyleIndex::Pokeball:
1058 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1059 drift_mode = controller.sixaxis_dual_left.gyroscope_zero_drift_mode;
1060 break;
1061 }
1062 drift_mode = controller.sixaxis_dual_right.gyroscope_zero_drift_mode;
1063 break;
1064 case Core::HID::NpadStyleIndex::JoyconLeft:
1065 drift_mode = controller.sixaxis_left.gyroscope_zero_drift_mode;
1066 break;
1067 case Core::HID::NpadStyleIndex::JoyconRight:
1068 drift_mode = controller.sixaxis_right.gyroscope_zero_drift_mode;
1069 break;
1070 default:
1071 LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
1072 return NpadInvalidHandle;
1073 }
1074 1060
1075 return ResultSuccess; 1061 return ResultSuccess;
1076} 1062}
1077 1063
1078ResultCode Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle, 1064ResultCode Controller_NPad::IsSixAxisSensorAtRest(
1079 bool& is_at_rest) const { 1065 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_at_rest) const {
1080 if (!IsDeviceHandleValid(sixaxis_handle)) { 1066 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1081 LOG_ERROR(Service_HID, "Invalid handle"); 1067 if (is_valid.IsError()) {
1082 return NpadInvalidHandle; 1068 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1069 return is_valid;
1083 } 1070 }
1071
1084 const auto& controller = GetControllerFromHandle(sixaxis_handle); 1072 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1085 is_at_rest = controller.sixaxis_at_rest; 1073 is_at_rest = controller.sixaxis_at_rest;
1086 return ResultSuccess; 1074 return ResultSuccess;
1087} 1075}
1088 1076
1089ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor( 1077ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1090 Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const { 1078 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
1091 if (!IsDeviceHandleValid(sixaxis_handle)) { 1079 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1092 LOG_ERROR(Service_HID, "Invalid handle"); 1080 if (is_valid.IsError()) {
1093 return NpadInvalidHandle; 1081 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1082 return is_valid;
1083 }
1084
1085 const auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle);
1086 is_firmware_available = sixaxis_properties.is_firmware_update_available != 0;
1087 return ResultSuccess;
1088}
1089
1090ResultCode Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
1091 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
1092 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1093 if (is_valid.IsError()) {
1094 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1095 return is_valid;
1096 }
1097
1098 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1099 sixaxis.unaltered_passtrough = is_enabled;
1100 return ResultSuccess;
1101}
1102
1103ResultCode Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
1104 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
1105 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1106 if (is_valid.IsError()) {
1107 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1108 return is_valid;
1109 }
1110
1111 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1112 is_enabled = sixaxis.unaltered_passtrough;
1113 return ResultSuccess;
1114}
1115
1116ResultCode Controller_NPad::LoadSixAxisSensorCalibrationParameter(
1117 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1118 Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
1119 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1120 if (is_valid.IsError()) {
1121 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1122 return is_valid;
1094 } 1123 }
1095 1124
1096 // We don't support joycon firmware updates 1125 // TODO: Request this data to the controller. On error return 0xd8ca
1097 is_firmware_available = false; 1126 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1127 calibration = sixaxis.calibration;
1098 return ResultSuccess; 1128 return ResultSuccess;
1099} 1129}
1100 1130
1101ResultCode Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, 1131ResultCode Controller_NPad::GetSixAxisSensorIcInformation(
1132 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1133 Core::HID::SixAxisSensorIcInformation& ic_information) const {
1134 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1135 if (is_valid.IsError()) {
1136 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1137 return is_valid;
1138 }
1139
1140 // TODO: Request this data to the controller. On error return 0xd8ca
1141 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1142 ic_information = sixaxis.ic_information;
1143 return ResultSuccess;
1144}
1145
1146ResultCode Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1147 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1148 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1149 if (is_valid.IsError()) {
1150 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1151 return is_valid;
1152 }
1153
1154 auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle);
1155 sixaxis_properties.is_newly_assigned.Assign(0);
1156
1157 return ResultSuccess;
1158}
1159
1160ResultCode Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1102 bool sixaxis_status) { 1161 bool sixaxis_status) {
1103 if (!IsDeviceHandleValid(sixaxis_handle)) { 1162 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1104 LOG_ERROR(Service_HID, "Invalid handle"); 1163 if (is_valid.IsError()) {
1105 return NpadInvalidHandle; 1164 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1165 return is_valid;
1106 } 1166 }
1167
1107 auto& controller = GetControllerFromHandle(sixaxis_handle); 1168 auto& controller = GetControllerFromHandle(sixaxis_handle);
1108 controller.sixaxis_sensor_enabled = sixaxis_status; 1169 controller.sixaxis_sensor_enabled = sixaxis_status;
1109 return ResultSuccess; 1170 return ResultSuccess;
1110} 1171}
1111 1172
1112ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled( 1173ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled(
1113 Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_fusion_enabled) const { 1174 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const {
1114 if (!IsDeviceHandleValid(sixaxis_handle)) { 1175 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1115 LOG_ERROR(Service_HID, "Invalid handle"); 1176 if (is_valid.IsError()) {
1116 return NpadInvalidHandle; 1177 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1178 return is_valid;
1117 } 1179 }
1118 1180
1119 auto& controller = GetControllerFromHandle(sixaxis_handle); 1181 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1120 switch (sixaxis_handle.npad_type) { 1182 is_fusion_enabled = sixaxis.is_fusion_enabled;
1121 case Core::HID::NpadStyleIndex::ProController:
1122 is_fusion_enabled = controller.sixaxis_fullkey.is_fusion_enabled;
1123 break;
1124 case Core::HID::NpadStyleIndex::Handheld:
1125 is_fusion_enabled = controller.sixaxis_handheld.is_fusion_enabled;
1126 break;
1127 case Core::HID::NpadStyleIndex::JoyconDual:
1128 case Core::HID::NpadStyleIndex::GameCube:
1129 case Core::HID::NpadStyleIndex::Pokeball:
1130 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1131 is_fusion_enabled = controller.sixaxis_dual_left.is_fusion_enabled;
1132 break;
1133 }
1134 is_fusion_enabled = controller.sixaxis_dual_right.is_fusion_enabled;
1135 break;
1136 case Core::HID::NpadStyleIndex::JoyconLeft:
1137 is_fusion_enabled = controller.sixaxis_left.is_fusion_enabled;
1138 break;
1139 case Core::HID::NpadStyleIndex::JoyconRight:
1140 is_fusion_enabled = controller.sixaxis_right.is_fusion_enabled;
1141 break;
1142 default:
1143 LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
1144 return NpadInvalidHandle;
1145 }
1146 1183
1147 return ResultSuccess; 1184 return ResultSuccess;
1148} 1185}
1149ResultCode Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, 1186ResultCode Controller_NPad::SetSixAxisFusionEnabled(
1150 bool is_fusion_enabled) { 1187 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
1151 if (!IsDeviceHandleValid(sixaxis_handle)) { 1188 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1152 LOG_ERROR(Service_HID, "Invalid handle"); 1189 if (is_valid.IsError()) {
1153 return NpadInvalidHandle; 1190 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1191 return is_valid;
1154 } 1192 }
1155 1193
1156 auto& controller = GetControllerFromHandle(sixaxis_handle); 1194 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1157 switch (sixaxis_handle.npad_type) { 1195 sixaxis.is_fusion_enabled = is_fusion_enabled;
1158 case Core::HID::NpadStyleIndex::ProController:
1159 controller.sixaxis_fullkey.is_fusion_enabled = is_fusion_enabled;
1160 break;
1161 case Core::HID::NpadStyleIndex::Handheld:
1162 controller.sixaxis_handheld.is_fusion_enabled = is_fusion_enabled;
1163 break;
1164 case Core::HID::NpadStyleIndex::JoyconDual:
1165 case Core::HID::NpadStyleIndex::GameCube:
1166 case Core::HID::NpadStyleIndex::Pokeball:
1167 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1168 controller.sixaxis_dual_left.is_fusion_enabled = is_fusion_enabled;
1169 break;
1170 }
1171 controller.sixaxis_dual_right.is_fusion_enabled = is_fusion_enabled;
1172 break;
1173 case Core::HID::NpadStyleIndex::JoyconLeft:
1174 controller.sixaxis_left.is_fusion_enabled = is_fusion_enabled;
1175 break;
1176 case Core::HID::NpadStyleIndex::JoyconRight:
1177 controller.sixaxis_right.is_fusion_enabled = is_fusion_enabled;
1178 break;
1179 default:
1180 LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
1181 return NpadInvalidHandle;
1182 }
1183 1196
1184 return ResultSuccess; 1197 return ResultSuccess;
1185} 1198}
1186 1199
1187ResultCode Controller_NPad::SetSixAxisFusionParameters( 1200ResultCode Controller_NPad::SetSixAxisFusionParameters(
1188 Core::HID::SixAxisSensorHandle sixaxis_handle, 1201 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1189 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { 1202 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
1190 if (!IsDeviceHandleValid(sixaxis_handle)) { 1203 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1191 LOG_ERROR(Service_HID, "Invalid handle"); 1204 if (is_valid.IsError()) {
1192 return NpadInvalidHandle; 1205 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1206 return is_valid;
1193 } 1207 }
1208
1194 const auto param1 = sixaxis_fusion_parameters.parameter1; 1209 const auto param1 = sixaxis_fusion_parameters.parameter1;
1195 if (param1 < 0.0f || param1 > 1.0f) { 1210 if (param1 < 0.0f || param1 > 1.0f) {
1196 return InvalidSixAxisFusionRange; 1211 return InvalidSixAxisFusionRange;
1197 } 1212 }
1198 1213
1199 auto& controller = GetControllerFromHandle(sixaxis_handle); 1214 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1200 switch (sixaxis_handle.npad_type) { 1215 sixaxis.fusion = sixaxis_fusion_parameters;
1201 case Core::HID::NpadStyleIndex::ProController:
1202 controller.sixaxis_fullkey.fusion = sixaxis_fusion_parameters;
1203 break;
1204 case Core::HID::NpadStyleIndex::Handheld:
1205 controller.sixaxis_handheld.fusion = sixaxis_fusion_parameters;
1206 break;
1207 case Core::HID::NpadStyleIndex::JoyconDual:
1208 case Core::HID::NpadStyleIndex::GameCube:
1209 case Core::HID::NpadStyleIndex::Pokeball:
1210 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1211 controller.sixaxis_dual_left.fusion = sixaxis_fusion_parameters;
1212 break;
1213 }
1214 controller.sixaxis_dual_right.fusion = sixaxis_fusion_parameters;
1215 break;
1216 case Core::HID::NpadStyleIndex::JoyconLeft:
1217 controller.sixaxis_left.fusion = sixaxis_fusion_parameters;
1218 break;
1219 case Core::HID::NpadStyleIndex::JoyconRight:
1220 controller.sixaxis_right.fusion = sixaxis_fusion_parameters;
1221 break;
1222 default:
1223 LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
1224 return NpadInvalidHandle;
1225 }
1226 1216
1227 return ResultSuccess; 1217 return ResultSuccess;
1228} 1218}
1229 1219
1230ResultCode Controller_NPad::GetSixAxisFusionParameters( 1220ResultCode Controller_NPad::GetSixAxisFusionParameters(
1231 Core::HID::SixAxisSensorHandle sixaxis_handle, 1221 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1232 Core::HID::SixAxisSensorFusionParameters& parameters) const { 1222 Core::HID::SixAxisSensorFusionParameters& parameters) const {
1233 if (!IsDeviceHandleValid(sixaxis_handle)) { 1223 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1234 LOG_ERROR(Service_HID, "Invalid handle"); 1224 if (is_valid.IsError()) {
1235 return NpadInvalidHandle; 1225 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1226 return is_valid;
1236 } 1227 }
1237 1228
1238 const auto& controller = GetControllerFromHandle(sixaxis_handle); 1229 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1239 switch (sixaxis_handle.npad_type) { 1230 parameters = sixaxis.fusion;
1240 case Core::HID::NpadStyleIndex::ProController:
1241 parameters = controller.sixaxis_fullkey.fusion;
1242 break;
1243 case Core::HID::NpadStyleIndex::Handheld:
1244 parameters = controller.sixaxis_handheld.fusion;
1245 break;
1246 case Core::HID::NpadStyleIndex::JoyconDual:
1247 case Core::HID::NpadStyleIndex::GameCube:
1248 case Core::HID::NpadStyleIndex::Pokeball:
1249 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1250 parameters = controller.sixaxis_dual_left.fusion;
1251 break;
1252 }
1253 parameters = controller.sixaxis_dual_right.fusion;
1254 break;
1255 case Core::HID::NpadStyleIndex::JoyconLeft:
1256 parameters = controller.sixaxis_left.fusion;
1257 break;
1258 case Core::HID::NpadStyleIndex::JoyconRight:
1259 parameters = controller.sixaxis_right.fusion;
1260 break;
1261 default:
1262 LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
1263 return NpadInvalidHandle;
1264 }
1265 1231
1266 return ResultSuccess; 1232 return ResultSuccess;
1267} 1233}
1268 1234
1269void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, 1235ResultCode Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1270 Core::HID::NpadIdType npad_id_2) { 1236 Core::HID::NpadIdType npad_id_2) {
1271 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1237 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1272 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1238 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1273 npad_id_2); 1239 npad_id_2);
1274 return; 1240 return InvalidNpadId;
1275 } 1241 }
1276 auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); 1242 auto& controller_1 = GetControllerFromNpadIdType(npad_id_1);
1277 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); 1243 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
1278 const auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); 1244 auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
1279 const auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); 1245 auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
1280 bool merge_controllers = false;
1281 1246
1282 // If the controllers at both npad indices form a pair of left and right joycons, merge them. 1247 // Simplify this code by converting dualjoycon with only a side connected to single joycons
1283 // Otherwise, do nothing. 1248 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) {
1249 if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
1250 controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft;
1251 }
1252 if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
1253 controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight;
1254 }
1255 }
1256 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
1257 if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
1258 controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft;
1259 }
1260 if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
1261 controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight;
1262 }
1263 }
1264
1265 // Invalid merge errors
1266 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual ||
1267 controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
1268 return NpadIsDualJoycon;
1269 }
1284 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && 1270 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
1271 controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) {
1272 return NpadIsSameType;
1273 }
1274 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
1285 controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { 1275 controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
1286 merge_controllers = true; 1276 return NpadIsSameType;
1287 } 1277 }
1288 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && 1278
1289 controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) { 1279 // These exceptions are handled as if they where dual joycon
1290 merge_controllers = true; 1280 if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft &&
1291 } 1281 controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) {
1292 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && 1282 return NpadIsDualJoycon;
1293 controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight &&
1294 controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
1295 merge_controllers = true;
1296 }
1297 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1298 controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
1299 !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
1300 merge_controllers = true;
1301 }
1302 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1303 controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
1304 controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
1305 merge_controllers = true;
1306 }
1307 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1308 controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
1309 !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
1310 merge_controllers = true;
1311 }
1312 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1313 controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1314 controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected &&
1315 !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
1316 merge_controllers = true;
1317 }
1318 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1319 controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1320 !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected &&
1321 controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
1322 merge_controllers = true;
1323 }
1324
1325 if (merge_controllers) {
1326 // Disconnect the joycon at the second id and connect the dual joycon at the first index.
1327 DisconnectNpad(npad_id_2);
1328 controller_1.is_dual_left_connected = true;
1329 controller_1.is_dual_right_connected = true;
1330 AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
1331 return;
1332 } 1283 }
1333 LOG_WARNING(Service_HID, 1284 if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft &&
1334 "Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, " 1285 controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) {
1335 "dual_1(left/right):{}/{}, dual_2(left/right):{}/{}", 1286 return NpadIsDualJoycon;
1336 npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(), 1287 }
1337 controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected, 1288
1338 controller_1.is_dual_right_connected, controller_2.is_dual_left_connected, 1289 // Disconnect the joycon at the second id and connect the dual joycon at the first index.
1339 controller_2.is_dual_right_connected); 1290 DisconnectNpad(npad_id_2);
1291 controller_1.is_dual_left_connected = true;
1292 controller_1.is_dual_right_connected = true;
1293 AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
1294 return ResultSuccess;
1340} 1295}
1341 1296
1342void Controller_NPad::StartLRAssignmentMode() { 1297void Controller_NPad::StartLRAssignmentMode() {
@@ -1349,17 +1304,17 @@ void Controller_NPad::StopLRAssignmentMode() {
1349 is_in_lr_assignment_mode = false; 1304 is_in_lr_assignment_mode = false;
1350} 1305}
1351 1306
1352bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, 1307ResultCode Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1353 Core::HID::NpadIdType npad_id_2) { 1308 Core::HID::NpadIdType npad_id_2) {
1354 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1309 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1355 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1310 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1356 npad_id_2); 1311 npad_id_2);
1357 return false; 1312 return InvalidNpadId;
1358 } 1313 }
1359 if (npad_id_1 == Core::HID::NpadIdType::Handheld || 1314 if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
1360 npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || 1315 npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
1361 npad_id_2 == Core::HID::NpadIdType::Other) { 1316 npad_id_2 == Core::HID::NpadIdType::Other) {
1362 return true; 1317 return ResultSuccess;
1363 } 1318 }
1364 const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; 1319 const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
1365 const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; 1320 const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
@@ -1369,46 +1324,49 @@ bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1369 const auto is_connected_2 = controller_2->IsConnected(); 1324 const auto is_connected_2 = controller_2->IsConnected();
1370 1325
1371 if (!IsControllerSupported(type_index_1) && is_connected_1) { 1326 if (!IsControllerSupported(type_index_1) && is_connected_1) {
1372 return false; 1327 return NpadNotConnected;
1373 } 1328 }
1374 if (!IsControllerSupported(type_index_2) && is_connected_2) { 1329 if (!IsControllerSupported(type_index_2) && is_connected_2) {
1375 return false; 1330 return NpadNotConnected;
1376 } 1331 }
1377 1332
1378 UpdateControllerAt(type_index_2, npad_id_1, is_connected_2); 1333 UpdateControllerAt(type_index_2, npad_id_1, is_connected_2);
1379 UpdateControllerAt(type_index_1, npad_id_2, is_connected_1); 1334 UpdateControllerAt(type_index_1, npad_id_2, is_connected_1);
1380 1335
1381 return true; 1336 return ResultSuccess;
1382} 1337}
1383 1338
1384Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) { 1339ResultCode Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
1340 Core::HID::LedPattern& pattern) const {
1385 if (!IsNpadIdValid(npad_id)) { 1341 if (!IsNpadIdValid(npad_id)) {
1386 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1342 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1387 return Core::HID::LedPattern{0, 0, 0, 0}; 1343 return InvalidNpadId;
1388 } 1344 }
1389 const auto& controller = GetControllerFromNpadIdType(npad_id).device; 1345 const auto& controller = GetControllerFromNpadIdType(npad_id).device;
1390 return controller->GetLedPattern(); 1346 pattern = controller->GetLedPattern();
1347 return ResultSuccess;
1391} 1348}
1392 1349
1393bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled( 1350ResultCode Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
1394 Core::HID::NpadIdType npad_id) const { 1351 Core::HID::NpadIdType npad_id, bool& is_valid) const {
1395 if (!IsNpadIdValid(npad_id)) { 1352 if (!IsNpadIdValid(npad_id)) {
1396 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1353 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1397 // Return the default value 1354 return InvalidNpadId;
1398 return false;
1399 } 1355 }
1400 const auto& controller = GetControllerFromNpadIdType(npad_id); 1356 const auto& controller = GetControllerFromNpadIdType(npad_id);
1401 return controller.unintended_home_button_input_protection; 1357 is_valid = controller.unintended_home_button_input_protection;
1358 return ResultSuccess;
1402} 1359}
1403 1360
1404void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, 1361ResultCode Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
1405 Core::HID::NpadIdType npad_id) { 1362 bool is_protection_enabled, Core::HID::NpadIdType npad_id) {
1406 if (!IsNpadIdValid(npad_id)) { 1363 if (!IsNpadIdValid(npad_id)) {
1407 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1364 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1408 return; 1365 return InvalidNpadId;
1409 } 1366 }
1410 auto& controller = GetControllerFromNpadIdType(npad_id); 1367 auto& controller = GetControllerFromNpadIdType(npad_id);
1411 controller.unintended_home_button_input_protection = is_protection_enabled; 1368 controller.unintended_home_button_input_protection = is_protection_enabled;
1369 return ResultSuccess;
1412} 1370}
1413 1371
1414void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { 1372void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
@@ -1546,4 +1504,96 @@ const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpa
1546 return controller_data[npad_index]; 1504 return controller_data[npad_index];
1547} 1505}
1548 1506
1507Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
1508 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1509 auto& controller = GetControllerFromHandle(sixaxis_handle);
1510 switch (sixaxis_handle.npad_type) {
1511 case Core::HID::NpadStyleIndex::ProController:
1512 case Core::HID::NpadStyleIndex::Pokeball:
1513 return controller.shared_memory->sixaxis_fullkey_properties;
1514 case Core::HID::NpadStyleIndex::Handheld:
1515 return controller.shared_memory->sixaxis_handheld_properties;
1516 case Core::HID::NpadStyleIndex::JoyconDual:
1517 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1518 return controller.shared_memory->sixaxis_dual_left_properties;
1519 }
1520 return controller.shared_memory->sixaxis_dual_right_properties;
1521 case Core::HID::NpadStyleIndex::JoyconLeft:
1522 return controller.shared_memory->sixaxis_left_properties;
1523 case Core::HID::NpadStyleIndex::JoyconRight:
1524 return controller.shared_memory->sixaxis_right_properties;
1525 default:
1526 return controller.shared_memory->sixaxis_fullkey_properties;
1527 }
1528}
1529
1530const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
1531 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
1532 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1533 switch (sixaxis_handle.npad_type) {
1534 case Core::HID::NpadStyleIndex::ProController:
1535 case Core::HID::NpadStyleIndex::Pokeball:
1536 return controller.shared_memory->sixaxis_fullkey_properties;
1537 case Core::HID::NpadStyleIndex::Handheld:
1538 return controller.shared_memory->sixaxis_handheld_properties;
1539 case Core::HID::NpadStyleIndex::JoyconDual:
1540 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1541 return controller.shared_memory->sixaxis_dual_left_properties;
1542 }
1543 return controller.shared_memory->sixaxis_dual_right_properties;
1544 case Core::HID::NpadStyleIndex::JoyconLeft:
1545 return controller.shared_memory->sixaxis_left_properties;
1546 case Core::HID::NpadStyleIndex::JoyconRight:
1547 return controller.shared_memory->sixaxis_right_properties;
1548 default:
1549 return controller.shared_memory->sixaxis_fullkey_properties;
1550 }
1551}
1552
1553Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
1554 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1555 auto& controller = GetControllerFromHandle(sixaxis_handle);
1556 switch (sixaxis_handle.npad_type) {
1557 case Core::HID::NpadStyleIndex::ProController:
1558 case Core::HID::NpadStyleIndex::Pokeball:
1559 return controller.sixaxis_fullkey;
1560 case Core::HID::NpadStyleIndex::Handheld:
1561 return controller.sixaxis_handheld;
1562 case Core::HID::NpadStyleIndex::JoyconDual:
1563 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1564 return controller.sixaxis_dual_left;
1565 }
1566 return controller.sixaxis_dual_right;
1567 case Core::HID::NpadStyleIndex::JoyconLeft:
1568 return controller.sixaxis_left;
1569 case Core::HID::NpadStyleIndex::JoyconRight:
1570 return controller.sixaxis_right;
1571 default:
1572 return controller.sixaxis_unknown;
1573 }
1574}
1575
1576const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
1577 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
1578 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1579 switch (sixaxis_handle.npad_type) {
1580 case Core::HID::NpadStyleIndex::ProController:
1581 case Core::HID::NpadStyleIndex::Pokeball:
1582 return controller.sixaxis_fullkey;
1583 case Core::HID::NpadStyleIndex::Handheld:
1584 return controller.sixaxis_handheld;
1585 case Core::HID::NpadStyleIndex::JoyconDual:
1586 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1587 return controller.sixaxis_dual_left;
1588 }
1589 return controller.sixaxis_dual_right;
1590 case Core::HID::NpadStyleIndex::JoyconLeft:
1591 return controller.sixaxis_left;
1592 case Core::HID::NpadStyleIndex::JoyconRight:
1593 return controller.sixaxis_right;
1594 default:
1595 return controller.sixaxis_unknown;
1596 }
1597}
1598
1549} // namespace Service::HID 1599} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 0a96825a5..0b662b7f8 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -107,8 +107,8 @@ public:
107 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); 107 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
108 NpadCommunicationMode GetNpadCommunicationMode() const; 108 NpadCommunicationMode GetNpadCommunicationMode() const;
109 109
110 void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, 110 ResultCode SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
111 NpadJoyAssignmentMode assignment_mode); 111 NpadJoyAssignmentMode assignment_mode);
112 112
113 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, 113 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
114 const Core::HID::VibrationValue& vibration_value); 114 const Core::HID::VibrationValue& vibration_value);
@@ -141,50 +141,65 @@ public:
141 void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, 141 void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id,
142 bool connected); 142 bool connected);
143 143
144 void DisconnectNpad(Core::HID::NpadIdType npad_id); 144 ResultCode DisconnectNpad(Core::HID::NpadIdType npad_id);
145 145
146 ResultCode SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, 146 ResultCode SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
147 GyroscopeZeroDriftMode drift_mode); 147 GyroscopeZeroDriftMode drift_mode);
148 ResultCode GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, 148 ResultCode GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
149 GyroscopeZeroDriftMode& drift_mode) const; 149 GyroscopeZeroDriftMode& drift_mode) const;
150 ResultCode IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle, 150 ResultCode IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
151 bool& is_at_rest) const; 151 bool& is_at_rest) const;
152 ResultCode IsFirmwareUpdateAvailableForSixAxisSensor( 152 ResultCode IsFirmwareUpdateAvailableForSixAxisSensor(
153 Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const; 153 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
154 ResultCode SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, 154 ResultCode EnableSixAxisSensorUnalteredPassthrough(
155 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
156 ResultCode IsSixAxisSensorUnalteredPassthroughEnabled(
157 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
158 ResultCode LoadSixAxisSensorCalibrationParameter(
159 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
160 Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
161 ResultCode GetSixAxisSensorIcInformation(
162 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
163 Core::HID::SixAxisSensorIcInformation& ic_information) const;
164 ResultCode ResetIsSixAxisSensorDeviceNewlyAssigned(
165 const Core::HID::SixAxisSensorHandle& sixaxis_handle);
166 ResultCode SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
155 bool sixaxis_status); 167 bool sixaxis_status);
156 ResultCode IsSixAxisSensorFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, 168 ResultCode IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
157 bool& is_fusion_enabled) const; 169 bool& is_fusion_enabled) const;
158 ResultCode SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, 170 ResultCode SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
159 bool is_fusion_enabled); 171 bool is_fusion_enabled);
160 ResultCode SetSixAxisFusionParameters( 172 ResultCode SetSixAxisFusionParameters(
161 Core::HID::SixAxisSensorHandle sixaxis_handle, 173 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
162 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); 174 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
163 ResultCode GetSixAxisFusionParameters( 175 ResultCode GetSixAxisFusionParameters(
164 Core::HID::SixAxisSensorHandle sixaxis_handle, 176 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
165 Core::HID::SixAxisSensorFusionParameters& parameters) const; 177 Core::HID::SixAxisSensorFusionParameters& parameters) const;
166 Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id); 178 ResultCode GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
167 bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const; 179 ResultCode IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
168 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, 180 bool& is_enabled) const;
169 Core::HID::NpadIdType npad_id); 181 ResultCode SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
182 Core::HID::NpadIdType npad_id);
170 void SetAnalogStickUseCenterClamp(bool use_center_clamp); 183 void SetAnalogStickUseCenterClamp(bool use_center_clamp);
171 void ClearAllConnectedControllers(); 184 void ClearAllConnectedControllers();
172 void DisconnectAllConnectedControllers(); 185 void DisconnectAllConnectedControllers();
173 void ConnectAllDisconnectedControllers(); 186 void ConnectAllDisconnectedControllers();
174 void ClearAllControllers(); 187 void ClearAllControllers();
175 188
176 void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); 189 ResultCode MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
190 Core::HID::NpadIdType npad_id_2);
177 void StartLRAssignmentMode(); 191 void StartLRAssignmentMode();
178 void StopLRAssignmentMode(); 192 void StopLRAssignmentMode();
179 bool SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); 193 ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
180 194
181 // Logical OR for all buttons presses on all controllers 195 // Logical OR for all buttons presses on all controllers
182 // Specifically for cheat engine and other features. 196 // Specifically for cheat engine and other features.
183 Core::HID::NpadButton GetAndResetPressState(); 197 Core::HID::NpadButton GetAndResetPressState();
184 198
185 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); 199 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
186 static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
187 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle); 200 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
201 static ResultCode VerifyValidSixAxisSensorHandle(
202 const Core::HID::SixAxisSensorHandle& device_handle);
188 203
189private: 204private:
190 static constexpr std::size_t NPAD_COUNT = 10; 205 static constexpr std::size_t NPAD_COUNT = 10;
@@ -451,9 +466,13 @@ private:
451 NpadLuciaType lucia_type{}; 466 NpadLuciaType lucia_type{};
452 NpadLagonType lagon_type{}; 467 NpadLagonType lagon_type{};
453 NpadLagerType lager_type{}; 468 NpadLagerType lager_type{};
454 // FW 13.x Investigate there is some sort of bitflag related to joycons 469 Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
455 INSERT_PADDING_BYTES(0x4); 470 Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
456 INSERT_PADDING_BYTES(0xc08); // Unknown 471 Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
472 Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
473 Core::HID::SixAxisSensorProperties sixaxis_left_properties;
474 Core::HID::SixAxisSensorProperties sixaxis_right_properties;
475 INSERT_PADDING_BYTES(0xc06); // Unknown
457 }; 476 };
458 static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); 477 static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
459 478
@@ -465,7 +484,10 @@ private:
465 484
466 struct SixaxisParameters { 485 struct SixaxisParameters {
467 bool is_fusion_enabled{true}; 486 bool is_fusion_enabled{true};
487 bool unaltered_passtrough{false};
468 Core::HID::SixAxisSensorFusionParameters fusion{}; 488 Core::HID::SixAxisSensorFusionParameters fusion{};
489 Core::HID::SixAxisSensorCalibrationParameter calibration{};
490 Core::HID::SixAxisSensorIcInformation ic_information{};
469 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; 491 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
470 }; 492 };
471 493
@@ -491,6 +513,7 @@ private:
491 SixaxisParameters sixaxis_dual_right{}; 513 SixaxisParameters sixaxis_dual_right{};
492 SixaxisParameters sixaxis_left{}; 514 SixaxisParameters sixaxis_left{};
493 SixaxisParameters sixaxis_right{}; 515 SixaxisParameters sixaxis_right{};
516 SixaxisParameters sixaxis_unknown{};
494 517
495 // Current pad state 518 // Current pad state
496 NPadGenericState npad_pad_state{}; 519 NPadGenericState npad_pad_state{};
@@ -522,6 +545,14 @@ private:
522 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); 545 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
523 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; 546 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
524 547
548 Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
549 const Core::HID::SixAxisSensorHandle& device_handle);
550 const Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
551 const Core::HID::SixAxisSensorHandle& device_handle) const;
552 SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
553 const SixaxisParameters& GetSixaxisState(
554 const Core::HID::SixAxisSensorHandle& device_handle) const;
555
525 std::atomic<u64> press_state{}; 556 std::atomic<u64> press_state{};
526 557
527 std::array<NpadControllerData, NPAD_COUNT> controller_data{}; 558 std::array<NpadControllerData, NPAD_COUNT> controller_data{};
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h
index b31834074..6c8ad04af 100644
--- a/src/core/hle/service/hid/errors.h
+++ b/src/core/hle/service/hid/errors.h
@@ -8,7 +8,11 @@
8namespace Service::HID { 8namespace Service::HID {
9 9
10constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100}; 10constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100};
11constexpr ResultCode NpadDeviceIndexOutOfRange{ErrorModule::HID, 107};
11constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423}; 12constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423};
13constexpr ResultCode NpadIsDualJoycon{ErrorModule::HID, 601};
14constexpr ResultCode NpadIsSameType{ErrorModule::HID, 602};
15constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709};
12constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710}; 16constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710};
13 17
14} // namespace Service::HID 18} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 44f892da9..8a496c38c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -257,12 +257,12 @@ Hid::Hid(Core::System& system_)
257 {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"}, 257 {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
258 {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"}, 258 {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
259 {83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"}, 259 {83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
260 {84, nullptr, "EnableSixAxisSensorUnalteredPassthrough"}, 260 {84, &Hid::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"},
261 {85, nullptr, "IsSixAxisSensorUnalteredPassthroughEnabled"}, 261 {85, &Hid::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"},
262 {86, nullptr, "StoreSixAxisSensorCalibrationParameter"}, 262 {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
263 {87, nullptr, "LoadSixAxisSensorCalibrationParameter"}, 263 {87, &Hid::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"},
264 {88, nullptr, "GetSixAxisSensorIcInformation"}, 264 {88, &Hid::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"},
265 {89, nullptr, "ResetIsSixAxisSensorDeviceNewlyAssigned"}, 265 {89, &Hid::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
266 {91, &Hid::ActivateGesture, "ActivateGesture"}, 266 {91, &Hid::ActivateGesture, "ActivateGesture"},
267 {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, 267 {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
268 {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"}, 268 {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
@@ -694,11 +694,7 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
694 rb.Push(result1); 694 rb.Push(result1);
695 return; 695 return;
696 } 696 }
697 if (result2.IsError()) { 697 rb.Push(result2);
698 rb.Push(result2);
699 return;
700 }
701 rb.Push(ResultSuccess);
702} 698}
703 699
704void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 700void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
@@ -821,6 +817,144 @@ void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& c
821 rb.Push(is_firmware_available); 817 rb.Push(is_firmware_available);
822} 818}
823 819
820void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx) {
821 IPC::RequestParser rp{ctx};
822 struct Parameters {
823 bool enabled;
824 Core::HID::SixAxisSensorHandle sixaxis_handle;
825 u64 applet_resource_user_id;
826 };
827 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
828
829 const auto parameters{rp.PopRaw<Parameters>()};
830
831 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
832 const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
833 parameters.sixaxis_handle, parameters.enabled);
834
835 LOG_WARNING(Service_HID,
836 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
837 "applet_resource_user_id={}",
838 parameters.enabled, parameters.sixaxis_handle.npad_type,
839 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
840 parameters.applet_resource_user_id);
841
842 IPC::ResponseBuilder rb{ctx, 2};
843 rb.Push(result);
844}
845
846void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx) {
847 IPC::RequestParser rp{ctx};
848 struct Parameters {
849 Core::HID::SixAxisSensorHandle sixaxis_handle;
850 INSERT_PADDING_WORDS_NOINIT(1);
851 u64 applet_resource_user_id;
852 };
853 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
854
855 const auto parameters{rp.PopRaw<Parameters>()};
856
857 bool is_unaltered_sisxaxis_enabled{};
858 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
859 const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
860 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
861
862 LOG_WARNING(
863 Service_HID,
864 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
865 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
866 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
867
868 IPC::ResponseBuilder rb{ctx, 3};
869 rb.Push(result);
870 rb.Push(is_unaltered_sisxaxis_enabled);
871}
872
873void Hid::LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx) {
874 IPC::RequestParser rp{ctx};
875 struct Parameters {
876 Core::HID::SixAxisSensorHandle sixaxis_handle;
877 INSERT_PADDING_WORDS_NOINIT(1);
878 u64 applet_resource_user_id;
879 };
880 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
881
882 const auto parameters{rp.PopRaw<Parameters>()};
883
884 Core::HID::SixAxisSensorCalibrationParameter calibration{};
885 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
886 const auto result =
887 controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
888
889 LOG_WARNING(
890 Service_HID,
891 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
892 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
893 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
894
895 if (result.IsSuccess()) {
896 ctx.WriteBuffer(calibration);
897 }
898
899 IPC::ResponseBuilder rb{ctx, 2};
900 rb.Push(result);
901}
902
903void Hid::GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx) {
904 IPC::RequestParser rp{ctx};
905 struct Parameters {
906 Core::HID::SixAxisSensorHandle sixaxis_handle;
907 INSERT_PADDING_WORDS_NOINIT(1);
908 u64 applet_resource_user_id;
909 };
910 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
911
912 const auto parameters{rp.PopRaw<Parameters>()};
913
914 Core::HID::SixAxisSensorIcInformation ic_information{};
915 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
916 const auto result =
917 controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
918
919 LOG_WARNING(
920 Service_HID,
921 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
922 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
923 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
924
925 if (result.IsSuccess()) {
926 ctx.WriteBuffer(ic_information);
927 }
928
929 IPC::ResponseBuilder rb{ctx, 2};
930 rb.Push(result);
931}
932
933void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx) {
934 IPC::RequestParser rp{ctx};
935 struct Parameters {
936 Core::HID::SixAxisSensorHandle sixaxis_handle;
937 INSERT_PADDING_WORDS_NOINIT(1);
938 u64 applet_resource_user_id;
939 };
940 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
941
942 const auto parameters{rp.PopRaw<Parameters>()};
943
944 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
945 const auto result =
946 controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
947
948 LOG_WARNING(
949 Service_HID,
950 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
951 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
952 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
953
954 IPC::ResponseBuilder rb{ctx, 2};
955 rb.Push(result);
956}
957
824void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { 958void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
825 IPC::RequestParser rp{ctx}; 959 IPC::RequestParser rp{ctx};
826 struct Parameters { 960 struct Parameters {
@@ -948,27 +1082,29 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
948 1082
949 const auto parameters{rp.PopRaw<Parameters>()}; 1083 const auto parameters{rp.PopRaw<Parameters>()};
950 1084
951 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1085 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
952 .DisconnectNpad(parameters.npad_id); 1086 const auto result = controller.DisconnectNpad(parameters.npad_id);
953 1087
954 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1088 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
955 parameters.applet_resource_user_id); 1089 parameters.applet_resource_user_id);
956 1090
957 IPC::ResponseBuilder rb{ctx, 2}; 1091 IPC::ResponseBuilder rb{ctx, 2};
958 rb.Push(ResultSuccess); 1092 rb.Push(result);
959} 1093}
960 1094
961void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { 1095void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
962 IPC::RequestParser rp{ctx}; 1096 IPC::RequestParser rp{ctx};
963 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; 1097 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
964 1098
1099 Core::HID::LedPattern pattern{0, 0, 0, 0};
1100 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1101 const auto result = controller.GetLedPattern(npad_id, pattern);
1102
965 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); 1103 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
966 1104
967 IPC::ResponseBuilder rb{ctx, 4}; 1105 IPC::ResponseBuilder rb{ctx, 4};
968 rb.Push(ResultSuccess); 1106 rb.Push(result);
969 rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) 1107 rb.Push(pattern.raw);
970 .GetLedPattern(npad_id)
971 .raw);
972} 1108}
973 1109
974void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { 1110void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
@@ -1028,15 +1164,16 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
1028 1164
1029 const auto parameters{rp.PopRaw<Parameters>()}; 1165 const auto parameters{rp.PopRaw<Parameters>()};
1030 1166
1031 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1167 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1032 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, 1168 const auto result =
1033 Controller_NPad::NpadJoyAssignmentMode::Single); 1169 controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left,
1170 Controller_NPad::NpadJoyAssignmentMode::Single);
1034 1171
1035 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1172 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1036 parameters.applet_resource_user_id); 1173 parameters.applet_resource_user_id);
1037 1174
1038 IPC::ResponseBuilder rb{ctx, 2}; 1175 IPC::ResponseBuilder rb{ctx, 2};
1039 rb.Push(ResultSuccess); 1176 rb.Push(result);
1040} 1177}
1041 1178
1042void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { 1179void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
@@ -1051,16 +1188,16 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
1051 1188
1052 const auto parameters{rp.PopRaw<Parameters>()}; 1189 const auto parameters{rp.PopRaw<Parameters>()};
1053 1190
1054 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1191 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1055 .SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, 1192 const auto result = controller.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type,
1056 Controller_NPad::NpadJoyAssignmentMode::Single); 1193 Controller_NPad::NpadJoyAssignmentMode::Single);
1057 1194
1058 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1195 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1059 parameters.npad_id, parameters.applet_resource_user_id, 1196 parameters.npad_id, parameters.applet_resource_user_id,
1060 parameters.npad_joy_device_type); 1197 parameters.npad_joy_device_type);
1061 1198
1062 IPC::ResponseBuilder rb{ctx, 2}; 1199 IPC::ResponseBuilder rb{ctx, 2};
1063 rb.Push(ResultSuccess); 1200 rb.Push(result);
1064} 1201}
1065 1202
1066void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { 1203void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
@@ -1074,14 +1211,15 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
1074 1211
1075 const auto parameters{rp.PopRaw<Parameters>()}; 1212 const auto parameters{rp.PopRaw<Parameters>()};
1076 1213
1077 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1214 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1078 .SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); 1215 const auto result = controller.SetNpadMode(parameters.npad_id, {},
1216 Controller_NPad::NpadJoyAssignmentMode::Dual);
1079 1217
1080 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1218 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1081 parameters.applet_resource_user_id); 1219 parameters.applet_resource_user_id);
1082 1220
1083 IPC::ResponseBuilder rb{ctx, 2}; 1221 IPC::ResponseBuilder rb{ctx, 2};
1084 rb.Push(ResultSuccess); 1222 rb.Push(result);
1085} 1223}
1086 1224
1087void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { 1225void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
@@ -1090,14 +1228,14 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
1090 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; 1228 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1091 const auto applet_resource_user_id{rp.Pop<u64>()}; 1229 const auto applet_resource_user_id{rp.Pop<u64>()};
1092 1230
1093 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1231 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1094 .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); 1232 const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
1095 1233
1096 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", 1234 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1097 npad_id_1, npad_id_2, applet_resource_user_id); 1235 npad_id_1, npad_id_2, applet_resource_user_id);
1098 1236
1099 IPC::ResponseBuilder rb{ctx, 2}; 1237 IPC::ResponseBuilder rb{ctx, 2};
1100 rb.Push(ResultSuccess); 1238 rb.Push(result);
1101} 1239}
1102 1240
1103void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { 1241void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
@@ -1157,19 +1295,14 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
1157 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; 1295 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1158 const auto applet_resource_user_id{rp.Pop<u64>()}; 1296 const auto applet_resource_user_id{rp.Pop<u64>()};
1159 1297
1160 const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) 1298 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1161 .SwapNpadAssignment(npad_id_1, npad_id_2); 1299 const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2);
1162 1300
1163 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", 1301 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1164 npad_id_1, npad_id_2, applet_resource_user_id); 1302 npad_id_1, npad_id_2, applet_resource_user_id);
1165 1303
1166 IPC::ResponseBuilder rb{ctx, 2}; 1304 IPC::ResponseBuilder rb{ctx, 2};
1167 if (res) { 1305 rb.Push(result);
1168 rb.Push(ResultSuccess);
1169 } else {
1170 LOG_ERROR(Service_HID, "Npads are not connected!");
1171 rb.Push(NpadNotConnected);
1172 }
1173} 1306}
1174 1307
1175void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { 1308void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
@@ -1183,13 +1316,17 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext
1183 1316
1184 const auto parameters{rp.PopRaw<Parameters>()}; 1317 const auto parameters{rp.PopRaw<Parameters>()};
1185 1318
1319 bool is_enabled = false;
1320 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1321 const auto result =
1322 controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
1323
1186 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 1324 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1187 parameters.npad_id, parameters.applet_resource_user_id); 1325 parameters.npad_id, parameters.applet_resource_user_id);
1188 1326
1189 IPC::ResponseBuilder rb{ctx, 3}; 1327 IPC::ResponseBuilder rb{ctx, 3};
1190 rb.Push(ResultSuccess); 1328 rb.Push(result);
1191 rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) 1329 rb.Push(is_enabled);
1192 .IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id));
1193} 1330}
1194 1331
1195void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { 1332void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) {
@@ -1204,9 +1341,9 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
1204 1341
1205 const auto parameters{rp.PopRaw<Parameters>()}; 1342 const auto parameters{rp.PopRaw<Parameters>()};
1206 1343
1207 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1344 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1208 .SetUnintendedHomeButtonInputProtectionEnabled( 1345 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
1209 parameters.unintended_home_button_input_protection, parameters.npad_id); 1346 parameters.unintended_home_button_input_protection, parameters.npad_id);
1210 1347
1211 LOG_WARNING(Service_HID, 1348 LOG_WARNING(Service_HID,
1212 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," 1349 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
@@ -1215,7 +1352,7 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
1215 parameters.applet_resource_user_id); 1352 parameters.applet_resource_user_id);
1216 1353
1217 IPC::ResponseBuilder rb{ctx, 2}; 1354 IPC::ResponseBuilder rb{ctx, 2};
1218 rb.Push(ResultSuccess); 1355 rb.Push(result);
1219} 1356}
1220 1357
1221void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { 1358void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
@@ -1377,6 +1514,8 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
1377 IPC::RequestParser rp{ctx}; 1514 IPC::RequestParser rp{ctx};
1378 const auto can_vibrate{rp.Pop<bool>()}; 1515 const auto can_vibrate{rp.Pop<bool>()};
1379 1516
1517 // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
1518 // by converting it to a bool
1380 Settings::values.vibration_enabled.SetValue(can_vibrate); 1519 Settings::values.vibration_enabled.SetValue(can_vibrate);
1381 1520
1382 LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); 1521 LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
@@ -1388,9 +1527,12 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
1388void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { 1527void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) {
1389 LOG_DEBUG(Service_HID, "called"); 1528 LOG_DEBUG(Service_HID, "called");
1390 1529
1530 // nnSDK checks if a float is greater than zero. We return the bool we stored earlier
1531 const auto is_enabled = Settings::values.vibration_enabled.GetValue();
1532
1391 IPC::ResponseBuilder rb{ctx, 3}; 1533 IPC::ResponseBuilder rb{ctx, 3};
1392 rb.Push(ResultSuccess); 1534 rb.Push(ResultSuccess);
1393 rb.Push(Settings::values.vibration_enabled.GetValue()); 1535 rb.Push(is_enabled);
1394} 1536}
1395 1537
1396void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { 1538void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 1be04c22b..ac4333022 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -113,6 +113,11 @@ private:
113 void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 113 void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
114 void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); 114 void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx);
115 void IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx); 115 void IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx);
116 void EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx);
117 void IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx);
118 void LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx);
119 void GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx);
120 void ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx);
116 void ActivateGesture(Kernel::HLERequestContext& ctx); 121 void ActivateGesture(Kernel::HLERequestContext& ctx);
117 void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); 122 void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
118 void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); 123 void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);