early-access version 2740
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| yuzu emulator early access | ||||
| ============= | ||||
|  | ||||
| This is the source code for early-access 2739. | ||||
| This is the source code for early-access 2740. | ||||
|  | ||||
| ## Legal Notice | ||||
|  | ||||
|   | ||||
| @@ -498,6 +498,49 @@ struct SixAxisSensorFusionParameters { | ||||
| static_assert(sizeof(SixAxisSensorFusionParameters) == 8, | ||||
|               "SixAxisSensorFusionParameters is an invalid size"); | ||||
|  | ||||
| // This is nn::hid::server::SixAxisSensorProperties | ||||
| struct SixAxisSensorProperties { | ||||
|     union { | ||||
|         u8 raw{}; | ||||
|         BitField<0, 1, u8> is_newly_assigned; | ||||
|         BitField<1, 1, u8> is_firmware_update_available; | ||||
|     }; | ||||
| }; | ||||
| static_assert(sizeof(SixAxisSensorProperties) == 1, "SixAxisSensorProperties is an invalid size"); | ||||
|  | ||||
| // This is nn::hid::SixAxisSensorCalibrationParameter | ||||
| struct SixAxisSensorCalibrationParameter { | ||||
|     std::array<u8, 0x744> unknown_data{}; | ||||
| }; | ||||
| static_assert(sizeof(SixAxisSensorCalibrationParameter) == 0x744, | ||||
|               "SixAxisSensorCalibrationParameter is an invalid size"); | ||||
|  | ||||
| // This is nn::hid::SixAxisSensorIcInformation | ||||
| struct SixAxisSensorIcInformation { | ||||
|     f32 angular_rate{2000.0f}; // dps | ||||
|     std::array<f32, 6> unknown_gyro_data1{ | ||||
|         -10.0f, -10.0f, -10.0f, 10.0f, 10.0f, 10.0f, | ||||
|     }; // dps | ||||
|     std::array<f32, 9> unknown_gyro_data2{ | ||||
|         0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, | ||||
|     }; | ||||
|     std::array<f32, 9> unknown_gyro_data3{ | ||||
|         1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, | ||||
|     }; | ||||
|     f32 acceleration_range{8.0f}; // g force | ||||
|     std::array<f32, 6> unknown_accel_data1{ | ||||
|         -0.0612f, -0.0612f, -0.0612f, 0.0612f, 0.0612f, 0.0612f, | ||||
|     }; // g force | ||||
|     std::array<f32, 9> unknown_accel_data2{ | ||||
|         0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, | ||||
|     }; | ||||
|     std::array<f32, 9> unknown_accel_data3{ | ||||
|         1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, | ||||
|     }; | ||||
| }; | ||||
| static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8, | ||||
|               "SixAxisSensorIcInformation is an invalid size"); | ||||
|  | ||||
| // This is nn::hid::VibrationDeviceHandle | ||||
| struct VibrationDeviceHandle { | ||||
|     NpadStyleIndex npad_type{NpadStyleIndex::None}; | ||||
|   | ||||
| @@ -56,11 +56,22 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle | ||||
|     return npad_id && npad_type && device_index; | ||||
| } | ||||
|  | ||||
| bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) { | ||||
| ResultCode Controller_NPad::VerifyValidSixAxisSensorHandle( | ||||
|     const Core::HID::SixAxisSensorHandle& device_handle) { | ||||
|     const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)); | ||||
|     const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType; | ||||
|     if (!npad_id) { | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|     const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; | ||||
|     return npad_id && npad_type && device_index; | ||||
|     if (!device_index) { | ||||
|         return NpadDeviceIndexOutOfRange; | ||||
|     } | ||||
|     // This doesn't get validated on nnsdk | ||||
|     const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType; | ||||
|     if (!npad_type) { | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| Controller_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) { | ||||
|         shared_memory->system_properties.use_plus.Assign(1); | ||||
|         shared_memory->system_properties.use_minus.Assign(1); | ||||
|         shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController; | ||||
|         shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         shared_memory->style_tag.handheld.Assign(1); | ||||
| @@ -170,16 +182,19 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | ||||
|         shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | ||||
|         shared_memory->applet_nfc_xcd.applet_footer.type = | ||||
|             AppletFooterUiType::HandheldJoyConLeftJoyConRight; | ||||
|         shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|         shared_memory->style_tag.joycon_dual.Assign(1); | ||||
|         if (controller.is_dual_left_connected) { | ||||
|             shared_memory->device_type.joycon_left.Assign(1); | ||||
|             shared_memory->system_properties.use_minus.Assign(1); | ||||
|             shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); | ||||
|         } | ||||
|         if (controller.is_dual_right_connected) { | ||||
|             shared_memory->device_type.joycon_right.Assign(1); | ||||
|             shared_memory->system_properties.use_plus.Assign(1); | ||||
|             shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); | ||||
|         } | ||||
|         shared_memory->system_properties.use_directional_buttons.Assign(1); | ||||
|         shared_memory->system_properties.is_vertical.Assign(1); | ||||
| @@ -198,6 +213,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | ||||
|         shared_memory->system_properties.is_horizontal.Assign(1); | ||||
|         shared_memory->system_properties.use_minus.Assign(1); | ||||
|         shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; | ||||
|         shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         shared_memory->style_tag.joycon_right.Assign(1); | ||||
| @@ -205,6 +221,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | ||||
|         shared_memory->system_properties.is_horizontal.Assign(1); | ||||
|         shared_memory->system_properties.use_plus.Assign(1); | ||||
|         shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; | ||||
|         shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|         shared_memory->style_tag.gamecube.Assign(1); | ||||
| @@ -215,6 +232,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         shared_memory->style_tag.palma.Assign(1); | ||||
|         shared_memory->device_type.palma.Assign(1); | ||||
|         shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::NES: | ||||
|         shared_memory->style_tag.lark.Assign(1); | ||||
| @@ -582,6 +600,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | ||||
|             UNREACHABLE(); | ||||
|             break; | ||||
|         case Core::HID::NpadStyleIndex::ProController: | ||||
|         case Core::HID::NpadStyleIndex::Pokeball: | ||||
|             set_motion_state(sixaxis_fullkey_state, motion_state[0]); | ||||
|             break; | ||||
|         case Core::HID::NpadStyleIndex::Handheld: | ||||
| @@ -672,6 +691,12 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { | ||||
| } | ||||
|  | ||||
| void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { | ||||
|     if (joy_hold_type != NpadJoyHoldType::Horizontal && | ||||
|         joy_hold_type != NpadJoyHoldType::Vertical) { | ||||
|         LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}", | ||||
|                   joy_hold_type); | ||||
|         return; | ||||
|     } | ||||
|     hold_type = joy_hold_type; | ||||
| } | ||||
|  | ||||
| @@ -695,11 +720,12 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode | ||||
|     return communication_mode; | ||||
| } | ||||
|  | ||||
| void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, | ||||
|                                   NpadJoyAssignmentMode assignment_mode) { | ||||
| ResultCode Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, | ||||
|                                         NpadJoyDeviceType npad_device_type, | ||||
|                                         NpadJoyAssignmentMode assignment_mode) { | ||||
|     if (!IsNpadIdValid(npad_id)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||||
|         return; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromNpadIdType(npad_id); | ||||
| @@ -708,7 +734,7 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy | ||||
|     } | ||||
|  | ||||
|     if (!controller.device->IsConnected()) { | ||||
|         return; | ||||
|         return ResultSuccess; | ||||
|     } | ||||
|  | ||||
|     if (assignment_mode == NpadJoyAssignmentMode::Dual) { | ||||
| @@ -717,34 +743,34 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy | ||||
|             controller.is_dual_left_connected = true; | ||||
|             controller.is_dual_right_connected = false; | ||||
|             UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); | ||||
|             return; | ||||
|             return ResultSuccess; | ||||
|         } | ||||
|         if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { | ||||
|             DisconnectNpad(npad_id); | ||||
|             controller.is_dual_left_connected = false; | ||||
|             controller.is_dual_right_connected = true; | ||||
|             UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); | ||||
|             return; | ||||
|             return ResultSuccess; | ||||
|         } | ||||
|         return; | ||||
|         return ResultSuccess; | ||||
|     } | ||||
|  | ||||
|     // This is for NpadJoyAssignmentMode::Single | ||||
|  | ||||
|     // Only JoyconDual get affected by this function | ||||
|     if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { | ||||
|         return; | ||||
|         return ResultSuccess; | ||||
|     } | ||||
|  | ||||
|     if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { | ||||
|         DisconnectNpad(npad_id); | ||||
|         UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); | ||||
|         return; | ||||
|         return ResultSuccess; | ||||
|     } | ||||
|     if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { | ||||
|         DisconnectNpad(npad_id); | ||||
|         UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); | ||||
|         return; | ||||
|         return ResultSuccess; | ||||
|     } | ||||
|  | ||||
|     // 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 | ||||
|         controller_2.is_dual_right_connected = false; | ||||
|         UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); | ||||
|     } | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, | ||||
| @@ -957,10 +984,10 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, | ||||
|     InitNewlyAddedController(npad_id); | ||||
| } | ||||
|  | ||||
| void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { | ||||
| ResultCode Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { | ||||
|     if (!IsNpadIdValid(npad_id)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||||
|         return; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|  | ||||
|     LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); | ||||
| @@ -977,6 +1004,12 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { | ||||
|     shared_memory->device_type.raw = 0; | ||||
|     shared_memory->system_properties.raw = 0; | ||||
|     shared_memory->button_properties.raw = 0; | ||||
|     shared_memory->sixaxis_fullkey_properties.raw = 0; | ||||
|     shared_memory->sixaxis_handheld_properties.raw = 0; | ||||
|     shared_memory->sixaxis_dual_left_properties.raw = 0; | ||||
|     shared_memory->sixaxis_dual_right_properties.raw = 0; | ||||
|     shared_memory->sixaxis_left_properties.raw = 0; | ||||
|     shared_memory->sixaxis_right_properties.raw = 0; | ||||
|     shared_memory->battery_level_dual = 0; | ||||
|     shared_memory->battery_level_left = 0; | ||||
|     shared_memory->battery_level_right = 0; | ||||
| @@ -997,346 +1030,268 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { | ||||
|     controller.device->Disconnect(); | ||||
|     SignalStyleSetChangedEvent(npad_id); | ||||
|     WriteEmptyEntry(shared_memory); | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|                                                       GyroscopeZeroDriftMode drift_mode) { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
| ResultCode Controller_NPad::SetGyroscopeZeroDriftMode( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|         controller.sixaxis_fullkey.gyroscope_zero_drift_mode = drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         controller.sixaxis_handheld.gyroscope_zero_drift_mode = drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             controller.sixaxis_dual_left.gyroscope_zero_drift_mode = drift_mode; | ||||
|             break; | ||||
|         } | ||||
|         controller.sixaxis_dual_right.gyroscope_zero_drift_mode = drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         controller.sixaxis_left.gyroscope_zero_drift_mode = drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         controller.sixaxis_right.gyroscope_zero_drift_mode = drift_mode; | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type); | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     sixaxis.gyroscope_zero_drift_mode = drift_mode; | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|                                                       GyroscopeZeroDriftMode& drift_mode) const { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
| ResultCode Controller_NPad::GetGyroscopeZeroDriftMode( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|     GyroscopeZeroDriftMode& drift_mode) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|         drift_mode = controller.sixaxis_fullkey.gyroscope_zero_drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         drift_mode = controller.sixaxis_handheld.gyroscope_zero_drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             drift_mode = controller.sixaxis_dual_left.gyroscope_zero_drift_mode; | ||||
|             break; | ||||
|         } | ||||
|         drift_mode = controller.sixaxis_dual_right.gyroscope_zero_drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         drift_mode = controller.sixaxis_left.gyroscope_zero_drift_mode; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         drift_mode = controller.sixaxis_right.gyroscope_zero_drift_mode; | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type); | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     drift_mode = sixaxis.gyroscope_zero_drift_mode; | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|                                                   bool& is_at_rest) const { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
| ResultCode Controller_NPad::IsSixAxisSensorAtRest( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_at_rest) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     is_at_rest = controller.sixaxis_at_rest; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor( | ||||
|     Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     // We don't support joycon firmware updates | ||||
|     is_firmware_available = false; | ||||
|     const auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle); | ||||
|     is_firmware_available = sixaxis_properties.is_firmware_update_available != 0; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|                                               bool sixaxis_status) { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
| ResultCode Controller_NPad::EnableSixAxisSensorUnalteredPassthrough( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     sixaxis.unaltered_passtrough = is_enabled; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     is_enabled = sixaxis.unaltered_passtrough; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::LoadSixAxisSensorCalibrationParameter( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|     Core::HID::SixAxisSensorCalibrationParameter& calibration) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     // TODO: Request this data to the controller. On error return 0xd8ca | ||||
|     const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     calibration = sixaxis.calibration; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::GetSixAxisSensorIcInformation( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|     Core::HID::SixAxisSensorIcInformation& ic_information) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     // TODO: Request this data to the controller. On error return 0xd8ca | ||||
|     const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     ic_information = sixaxis.ic_information; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle); | ||||
|     sixaxis_properties.is_newly_assigned.Assign(0); | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                               bool sixaxis_status) { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     controller.sixaxis_sensor_enabled = sixaxis_status; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled( | ||||
|     Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_fusion_enabled) const { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|         is_fusion_enabled = controller.sixaxis_fullkey.is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         is_fusion_enabled = controller.sixaxis_handheld.is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             is_fusion_enabled = controller.sixaxis_dual_left.is_fusion_enabled; | ||||
|             break; | ||||
|         } | ||||
|         is_fusion_enabled = controller.sixaxis_dual_right.is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         is_fusion_enabled = controller.sixaxis_left.is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         is_fusion_enabled = controller.sixaxis_right.is_fusion_enabled; | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type); | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     is_fusion_enabled = sixaxis.is_fusion_enabled; | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
| ResultCode Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|                                                     bool is_fusion_enabled) { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
| ResultCode Controller_NPad::SetSixAxisFusionEnabled( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) { | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|         controller.sixaxis_fullkey.is_fusion_enabled = is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         controller.sixaxis_handheld.is_fusion_enabled = is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             controller.sixaxis_dual_left.is_fusion_enabled = is_fusion_enabled; | ||||
|             break; | ||||
|         } | ||||
|         controller.sixaxis_dual_right.is_fusion_enabled = is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         controller.sixaxis_left.is_fusion_enabled = is_fusion_enabled; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         controller.sixaxis_right.is_fusion_enabled = is_fusion_enabled; | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type); | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     sixaxis.is_fusion_enabled = is_fusion_enabled; | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::SetSixAxisFusionParameters( | ||||
|     Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|     Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     const auto param1 = sixaxis_fusion_parameters.parameter1; | ||||
|     if (param1 < 0.0f || param1 > 1.0f) { | ||||
|         return InvalidSixAxisFusionRange; | ||||
|     } | ||||
|  | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|         controller.sixaxis_fullkey.fusion = sixaxis_fusion_parameters; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         controller.sixaxis_handheld.fusion = sixaxis_fusion_parameters; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             controller.sixaxis_dual_left.fusion = sixaxis_fusion_parameters; | ||||
|             break; | ||||
|         } | ||||
|         controller.sixaxis_dual_right.fusion = sixaxis_fusion_parameters; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         controller.sixaxis_left.fusion = sixaxis_fusion_parameters; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         controller.sixaxis_right.fusion = sixaxis_fusion_parameters; | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type); | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     sixaxis.fusion = sixaxis_fusion_parameters; | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| ResultCode Controller_NPad::GetSixAxisFusionParameters( | ||||
|     Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|     Core::HID::SixAxisSensorFusionParameters& parameters) const { | ||||
|     if (!IsDeviceHandleValid(sixaxis_handle)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle"); | ||||
|         return NpadInvalidHandle; | ||||
|     const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); | ||||
|     if (is_valid.IsError()) { | ||||
|         LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||||
|         return is_valid; | ||||
|     } | ||||
|  | ||||
|     const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|         parameters = controller.sixaxis_fullkey.fusion; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         parameters = controller.sixaxis_handheld.fusion; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|     case Core::HID::NpadStyleIndex::GameCube: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             parameters = controller.sixaxis_dual_left.fusion; | ||||
|             break; | ||||
|         } | ||||
|         parameters = controller.sixaxis_dual_right.fusion; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         parameters = controller.sixaxis_left.fusion; | ||||
|         break; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         parameters = controller.sixaxis_right.fusion; | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type); | ||||
|         return NpadInvalidHandle; | ||||
|     } | ||||
|     const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||||
|     parameters = sixaxis.fusion; | ||||
|  | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, | ||||
|                                               Core::HID::NpadIdType npad_id_2) { | ||||
| ResultCode Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, | ||||
|                                                     Core::HID::NpadIdType npad_id_2) { | ||||
|     if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||||
|                   npad_id_2); | ||||
|         return; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|     auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); | ||||
|     auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); | ||||
|     const auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); | ||||
|     const auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); | ||||
|     bool merge_controllers = false; | ||||
|     auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); | ||||
|     auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); | ||||
|  | ||||
|     // If the controllers at both npad indices form a pair of left and right joycons, merge them. | ||||
|     // Otherwise, do nothing. | ||||
|     // Simplify this code by converting dualjoycon with only a side connected to single joycons | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) { | ||||
|         if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { | ||||
|             controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft; | ||||
|         } | ||||
|         if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { | ||||
|             controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight; | ||||
|         } | ||||
|     } | ||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||||
|         if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { | ||||
|             controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft; | ||||
|         } | ||||
|         if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { | ||||
|             controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Invalid merge errors | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual || | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||||
|         return NpadIsDualJoycon; | ||||
|     } | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) { | ||||
|         return NpadIsSameType; | ||||
|     } | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && | ||||
|         controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight && | ||||
|         controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && | ||||
|         !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && | ||||
|         controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && | ||||
|         !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected && | ||||
|         !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { | ||||
|         merge_controllers = true; | ||||
|     } | ||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && | ||||
|         !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected && | ||||
|         controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { | ||||
|         merge_controllers = true; | ||||
|         return NpadIsSameType; | ||||
|     } | ||||
|  | ||||
|     if (merge_controllers) { | ||||
|         // Disconnect the joycon at the second id and connect the dual joycon at the first index. | ||||
|         DisconnectNpad(npad_id_2); | ||||
|         controller_1.is_dual_left_connected = true; | ||||
|         controller_1.is_dual_right_connected = true; | ||||
|         AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); | ||||
|         return; | ||||
|     // These exceptions are handled as if they where dual joycon | ||||
|     if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft && | ||||
|         controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) { | ||||
|         return NpadIsDualJoycon; | ||||
|     } | ||||
|     LOG_WARNING(Service_HID, | ||||
|                 "Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, " | ||||
|                 "dual_1(left/right):{}/{}, dual_2(left/right):{}/{}", | ||||
|                 npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(), | ||||
|                 controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected, | ||||
|                 controller_1.is_dual_right_connected, controller_2.is_dual_left_connected, | ||||
|                 controller_2.is_dual_right_connected); | ||||
|     if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft && | ||||
|         controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) { | ||||
|         return NpadIsDualJoycon; | ||||
|     } | ||||
|  | ||||
|     // Disconnect the joycon at the second id and connect the dual joycon at the first index. | ||||
|     DisconnectNpad(npad_id_2); | ||||
|     controller_1.is_dual_left_connected = true; | ||||
|     controller_1.is_dual_right_connected = true; | ||||
|     AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| void Controller_NPad::StartLRAssignmentMode() { | ||||
| @@ -1349,17 +1304,17 @@ void Controller_NPad::StopLRAssignmentMode() { | ||||
|     is_in_lr_assignment_mode = false; | ||||
| } | ||||
|  | ||||
| bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, | ||||
|                                          Core::HID::NpadIdType npad_id_2) { | ||||
| ResultCode Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, | ||||
|                                                Core::HID::NpadIdType npad_id_2) { | ||||
|     if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||||
|                   npad_id_2); | ||||
|         return false; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|     if (npad_id_1 == Core::HID::NpadIdType::Handheld || | ||||
|         npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || | ||||
|         npad_id_2 == Core::HID::NpadIdType::Other) { | ||||
|         return true; | ||||
|         return ResultSuccess; | ||||
|     } | ||||
|     const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; | ||||
|     const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; | ||||
| @@ -1369,46 +1324,49 @@ bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, | ||||
|     const auto is_connected_2 = controller_2->IsConnected(); | ||||
|  | ||||
|     if (!IsControllerSupported(type_index_1) && is_connected_1) { | ||||
|         return false; | ||||
|         return NpadNotConnected; | ||||
|     } | ||||
|     if (!IsControllerSupported(type_index_2) && is_connected_2) { | ||||
|         return false; | ||||
|         return NpadNotConnected; | ||||
|     } | ||||
|  | ||||
|     UpdateControllerAt(type_index_2, npad_id_1, is_connected_2); | ||||
|     UpdateControllerAt(type_index_1, npad_id_2, is_connected_1); | ||||
|  | ||||
|     return true; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) { | ||||
| ResultCode Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id, | ||||
|                                           Core::HID::LedPattern& pattern) const { | ||||
|     if (!IsNpadIdValid(npad_id)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||||
|         return Core::HID::LedPattern{0, 0, 0, 0}; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|     const auto& controller = GetControllerFromNpadIdType(npad_id).device; | ||||
|     return controller->GetLedPattern(); | ||||
|     pattern = controller->GetLedPattern(); | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled( | ||||
|     Core::HID::NpadIdType npad_id) const { | ||||
| ResultCode Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled( | ||||
|     Core::HID::NpadIdType npad_id, bool& is_valid) const { | ||||
|     if (!IsNpadIdValid(npad_id)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||||
|         // Return the default value | ||||
|         return false; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|     const auto& controller = GetControllerFromNpadIdType(npad_id); | ||||
|     return controller.unintended_home_button_input_protection; | ||||
|     is_valid = controller.unintended_home_button_input_protection; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, | ||||
|                                                                     Core::HID::NpadIdType npad_id) { | ||||
| ResultCode Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled( | ||||
|     bool is_protection_enabled, Core::HID::NpadIdType npad_id) { | ||||
|     if (!IsNpadIdValid(npad_id)) { | ||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||||
|         return; | ||||
|         return InvalidNpadId; | ||||
|     } | ||||
|     auto& controller = GetControllerFromNpadIdType(npad_id); | ||||
|     controller.unintended_home_button_input_protection = is_protection_enabled; | ||||
|     return ResultSuccess; | ||||
| } | ||||
|  | ||||
| void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { | ||||
| @@ -1546,4 +1504,96 @@ const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpa | ||||
|     return controller_data[npad_index]; | ||||
| } | ||||
|  | ||||
| Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         return controller.shared_memory->sixaxis_fullkey_properties; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         return controller.shared_memory->sixaxis_handheld_properties; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             return controller.shared_memory->sixaxis_dual_left_properties; | ||||
|         } | ||||
|         return controller.shared_memory->sixaxis_dual_right_properties; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         return controller.shared_memory->sixaxis_left_properties; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         return controller.shared_memory->sixaxis_right_properties; | ||||
|     default: | ||||
|         return controller.shared_memory->sixaxis_fullkey_properties; | ||||
|     } | ||||
| } | ||||
|  | ||||
| const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | ||||
|     const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         return controller.shared_memory->sixaxis_fullkey_properties; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         return controller.shared_memory->sixaxis_handheld_properties; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             return controller.shared_memory->sixaxis_dual_left_properties; | ||||
|         } | ||||
|         return controller.shared_memory->sixaxis_dual_right_properties; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         return controller.shared_memory->sixaxis_left_properties; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         return controller.shared_memory->sixaxis_right_properties; | ||||
|     default: | ||||
|         return controller.shared_memory->sixaxis_fullkey_properties; | ||||
|     } | ||||
| } | ||||
|  | ||||
| Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||||
|     auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         return controller.sixaxis_fullkey; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         return controller.sixaxis_handheld; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             return controller.sixaxis_dual_left; | ||||
|         } | ||||
|         return controller.sixaxis_dual_right; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         return controller.sixaxis_left; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         return controller.sixaxis_right; | ||||
|     default: | ||||
|         return controller.sixaxis_unknown; | ||||
|     } | ||||
| } | ||||
|  | ||||
| const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState( | ||||
|     const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | ||||
|     const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||||
|     switch (sixaxis_handle.npad_type) { | ||||
|     case Core::HID::NpadStyleIndex::ProController: | ||||
|     case Core::HID::NpadStyleIndex::Pokeball: | ||||
|         return controller.sixaxis_fullkey; | ||||
|     case Core::HID::NpadStyleIndex::Handheld: | ||||
|         return controller.sixaxis_handheld; | ||||
|     case Core::HID::NpadStyleIndex::JoyconDual: | ||||
|         if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||||
|             return controller.sixaxis_dual_left; | ||||
|         } | ||||
|         return controller.sixaxis_dual_right; | ||||
|     case Core::HID::NpadStyleIndex::JoyconLeft: | ||||
|         return controller.sixaxis_left; | ||||
|     case Core::HID::NpadStyleIndex::JoyconRight: | ||||
|         return controller.sixaxis_right; | ||||
|     default: | ||||
|         return controller.sixaxis_unknown; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace Service::HID | ||||
|   | ||||
| @@ -107,8 +107,8 @@ public: | ||||
|     void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); | ||||
|     NpadCommunicationMode GetNpadCommunicationMode() const; | ||||
|  | ||||
|     void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, | ||||
|                      NpadJoyAssignmentMode assignment_mode); | ||||
|     ResultCode SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, | ||||
|                            NpadJoyAssignmentMode assignment_mode); | ||||
|  | ||||
|     bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, | ||||
|                                   const Core::HID::VibrationValue& vibration_value); | ||||
| @@ -141,50 +141,65 @@ public: | ||||
|     void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, | ||||
|                             bool connected); | ||||
|  | ||||
|     void DisconnectNpad(Core::HID::NpadIdType npad_id); | ||||
|     ResultCode DisconnectNpad(Core::HID::NpadIdType npad_id); | ||||
|  | ||||
|     ResultCode SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     ResultCode SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                          GyroscopeZeroDriftMode drift_mode); | ||||
|     ResultCode GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     ResultCode GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                          GyroscopeZeroDriftMode& drift_mode) const; | ||||
|     ResultCode IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     ResultCode IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                      bool& is_at_rest) const; | ||||
|     ResultCode IsFirmwareUpdateAvailableForSixAxisSensor( | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const; | ||||
|     ResultCode SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const; | ||||
|     ResultCode EnableSixAxisSensorUnalteredPassthrough( | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled); | ||||
|     ResultCode IsSixAxisSensorUnalteredPassthroughEnabled( | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const; | ||||
|     ResultCode LoadSixAxisSensorCalibrationParameter( | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|         Core::HID::SixAxisSensorCalibrationParameter& calibration) const; | ||||
|     ResultCode GetSixAxisSensorIcInformation( | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|         Core::HID::SixAxisSensorIcInformation& ic_information) const; | ||||
|     ResultCode ResetIsSixAxisSensorDeviceNewlyAssigned( | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle); | ||||
|     ResultCode SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                  bool sixaxis_status); | ||||
|     ResultCode IsSixAxisSensorFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     ResultCode IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                             bool& is_fusion_enabled) const; | ||||
|     ResultCode SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|     ResultCode SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|                                        bool is_fusion_enabled); | ||||
|     ResultCode SetSixAxisFusionParameters( | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|         Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); | ||||
|     ResultCode GetSixAxisFusionParameters( | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle, | ||||
|         const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||||
|         Core::HID::SixAxisSensorFusionParameters& parameters) const; | ||||
|     Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id); | ||||
|     bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const; | ||||
|     void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, | ||||
|                                                        Core::HID::NpadIdType npad_id); | ||||
|     ResultCode GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; | ||||
|     ResultCode IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, | ||||
|                                                             bool& is_enabled) const; | ||||
|     ResultCode SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, | ||||
|                                                              Core::HID::NpadIdType npad_id); | ||||
|     void SetAnalogStickUseCenterClamp(bool use_center_clamp); | ||||
|     void ClearAllConnectedControllers(); | ||||
|     void DisconnectAllConnectedControllers(); | ||||
|     void ConnectAllDisconnectedControllers(); | ||||
|     void ClearAllControllers(); | ||||
|  | ||||
|     void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); | ||||
|     ResultCode MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, | ||||
|                                        Core::HID::NpadIdType npad_id_2); | ||||
|     void StartLRAssignmentMode(); | ||||
|     void StopLRAssignmentMode(); | ||||
|     bool SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); | ||||
|     ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); | ||||
|  | ||||
|     // Logical OR for all buttons presses on all controllers | ||||
|     // Specifically for cheat engine and other features. | ||||
|     Core::HID::NpadButton GetAndResetPressState(); | ||||
|  | ||||
|     static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); | ||||
|     static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle); | ||||
|     static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle); | ||||
|     static ResultCode VerifyValidSixAxisSensorHandle( | ||||
|         const Core::HID::SixAxisSensorHandle& device_handle); | ||||
|  | ||||
| private: | ||||
|     static constexpr std::size_t NPAD_COUNT = 10; | ||||
| @@ -451,9 +466,13 @@ private: | ||||
|         NpadLuciaType lucia_type{}; | ||||
|         NpadLagonType lagon_type{}; | ||||
|         NpadLagerType lager_type{}; | ||||
|         // FW 13.x Investigate there is some sort of bitflag related to joycons | ||||
|         INSERT_PADDING_BYTES(0x4); | ||||
|         INSERT_PADDING_BYTES(0xc08); // Unknown | ||||
|         Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties; | ||||
|         Core::HID::SixAxisSensorProperties sixaxis_handheld_properties; | ||||
|         Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties; | ||||
|         Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties; | ||||
|         Core::HID::SixAxisSensorProperties sixaxis_left_properties; | ||||
|         Core::HID::SixAxisSensorProperties sixaxis_right_properties; | ||||
|         INSERT_PADDING_BYTES(0xc06); // Unknown | ||||
|     }; | ||||
|     static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); | ||||
|  | ||||
| @@ -465,7 +484,10 @@ private: | ||||
|  | ||||
|     struct SixaxisParameters { | ||||
|         bool is_fusion_enabled{true}; | ||||
|         bool unaltered_passtrough{false}; | ||||
|         Core::HID::SixAxisSensorFusionParameters fusion{}; | ||||
|         Core::HID::SixAxisSensorCalibrationParameter calibration{}; | ||||
|         Core::HID::SixAxisSensorIcInformation ic_information{}; | ||||
|         GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; | ||||
|     }; | ||||
|  | ||||
| @@ -491,6 +513,7 @@ private: | ||||
|         SixaxisParameters sixaxis_dual_right{}; | ||||
|         SixaxisParameters sixaxis_left{}; | ||||
|         SixaxisParameters sixaxis_right{}; | ||||
|         SixaxisParameters sixaxis_unknown{}; | ||||
|  | ||||
|         // Current pad state | ||||
|         NPadGenericState npad_pad_state{}; | ||||
| @@ -522,6 +545,14 @@ private: | ||||
|     NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); | ||||
|     const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; | ||||
|  | ||||
|     Core::HID::SixAxisSensorProperties& GetSixaxisProperties( | ||||
|         const Core::HID::SixAxisSensorHandle& device_handle); | ||||
|     const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( | ||||
|         const Core::HID::SixAxisSensorHandle& device_handle) const; | ||||
|     SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle); | ||||
|     const SixaxisParameters& GetSixaxisState( | ||||
|         const Core::HID::SixAxisSensorHandle& device_handle) const; | ||||
|  | ||||
|     std::atomic<u64> press_state{}; | ||||
|  | ||||
|     std::array<NpadControllerData, NPAD_COUNT> controller_data{}; | ||||
|   | ||||
| @@ -8,7 +8,11 @@ | ||||
| namespace Service::HID { | ||||
|  | ||||
| constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100}; | ||||
| constexpr ResultCode NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; | ||||
| constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423}; | ||||
| constexpr ResultCode NpadIsDualJoycon{ErrorModule::HID, 601}; | ||||
| constexpr ResultCode NpadIsSameType{ErrorModule::HID, 602}; | ||||
| constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709}; | ||||
| constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710}; | ||||
|  | ||||
| } // namespace Service::HID | ||||
|   | ||||
| @@ -257,12 +257,12 @@ Hid::Hid(Core::System& system_) | ||||
|         {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"}, | ||||
|         {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"}, | ||||
|         {83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"}, | ||||
|         {84, nullptr, "EnableSixAxisSensorUnalteredPassthrough"}, | ||||
|         {85, nullptr, "IsSixAxisSensorUnalteredPassthroughEnabled"}, | ||||
|         {84, &Hid::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"}, | ||||
|         {85, &Hid::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"}, | ||||
|         {86, nullptr, "StoreSixAxisSensorCalibrationParameter"}, | ||||
|         {87, nullptr, "LoadSixAxisSensorCalibrationParameter"}, | ||||
|         {88, nullptr, "GetSixAxisSensorIcInformation"}, | ||||
|         {89, nullptr, "ResetIsSixAxisSensorDeviceNewlyAssigned"}, | ||||
|         {87, &Hid::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"}, | ||||
|         {88, &Hid::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"}, | ||||
|         {89, &Hid::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"}, | ||||
|         {91, &Hid::ActivateGesture, "ActivateGesture"}, | ||||
|         {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, | ||||
|         {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"}, | ||||
| @@ -694,11 +694,7 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { | ||||
|         rb.Push(result1); | ||||
|         return; | ||||
|     } | ||||
|     if (result2.IsError()) { | ||||
|         rb.Push(result2); | ||||
|         return; | ||||
|     } | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result2); | ||||
| } | ||||
|  | ||||
| void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | ||||
| @@ -821,6 +817,144 @@ void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& c | ||||
|     rb.Push(is_firmware_available); | ||||
| } | ||||
|  | ||||
| void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     struct Parameters { | ||||
|         bool enabled; | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle; | ||||
|         u64 applet_resource_user_id; | ||||
|     }; | ||||
|     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.EnableSixAxisSensorUnalteredPassthrough( | ||||
|         parameters.sixaxis_handle, parameters.enabled); | ||||
|  | ||||
|     LOG_WARNING(Service_HID, | ||||
|                 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, " | ||||
|                 "applet_resource_user_id={}", | ||||
|                 parameters.enabled, parameters.sixaxis_handle.npad_type, | ||||
|                 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, | ||||
|                 parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     struct Parameters { | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle; | ||||
|         INSERT_PADDING_WORDS_NOINIT(1); | ||||
|         u64 applet_resource_user_id; | ||||
|     }; | ||||
|     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     bool is_unaltered_sisxaxis_enabled{}; | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled( | ||||
|         parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled); | ||||
|  | ||||
|     LOG_WARNING( | ||||
|         Service_HID, | ||||
|         "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||||
|         parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||||
|         parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(result); | ||||
|     rb.Push(is_unaltered_sisxaxis_enabled); | ||||
| } | ||||
|  | ||||
| void Hid::LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     struct Parameters { | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle; | ||||
|         INSERT_PADDING_WORDS_NOINIT(1); | ||||
|         u64 applet_resource_user_id; | ||||
|     }; | ||||
|     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     Core::HID::SixAxisSensorCalibrationParameter calibration{}; | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = | ||||
|         controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration); | ||||
|  | ||||
|     LOG_WARNING( | ||||
|         Service_HID, | ||||
|         "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||||
|         parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||||
|         parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||||
|  | ||||
|     if (result.IsSuccess()) { | ||||
|         ctx.WriteBuffer(calibration); | ||||
|     } | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     struct Parameters { | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle; | ||||
|         INSERT_PADDING_WORDS_NOINIT(1); | ||||
|         u64 applet_resource_user_id; | ||||
|     }; | ||||
|     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     Core::HID::SixAxisSensorIcInformation ic_information{}; | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = | ||||
|         controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information); | ||||
|  | ||||
|     LOG_WARNING( | ||||
|         Service_HID, | ||||
|         "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||||
|         parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||||
|         parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||||
|  | ||||
|     if (result.IsSuccess()) { | ||||
|         ctx.WriteBuffer(ic_information); | ||||
|     } | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     struct Parameters { | ||||
|         Core::HID::SixAxisSensorHandle sixaxis_handle; | ||||
|         INSERT_PADDING_WORDS_NOINIT(1); | ||||
|         u64 applet_resource_user_id; | ||||
|     }; | ||||
|     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = | ||||
|         controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle); | ||||
|  | ||||
|     LOG_WARNING( | ||||
|         Service_HID, | ||||
|         "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||||
|         parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||||
|         parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     struct Parameters { | ||||
| @@ -948,27 +1082,29 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .DisconnectNpad(parameters.npad_id); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.DisconnectNpad(parameters.npad_id); | ||||
|  | ||||
|     LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, | ||||
|               parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; | ||||
|  | ||||
|     Core::HID::LedPattern pattern{0, 0, 0, 0}; | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.GetLedPattern(npad_id, pattern); | ||||
|  | ||||
|     LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|                 .GetLedPattern(npad_id) | ||||
|                 .raw); | ||||
|     rb.Push(result); | ||||
|     rb.Push(pattern.raw); | ||||
| } | ||||
|  | ||||
| void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1028,15 +1164,16 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, | ||||
|                      Controller_NPad::NpadJoyAssignmentMode::Single); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = | ||||
|         controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, | ||||
|                                Controller_NPad::NpadJoyAssignmentMode::Single); | ||||
|  | ||||
|     LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, | ||||
|              parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1051,16 +1188,16 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, | ||||
|                      Controller_NPad::NpadJoyAssignmentMode::Single); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, | ||||
|                                                Controller_NPad::NpadJoyAssignmentMode::Single); | ||||
|  | ||||
|     LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", | ||||
|              parameters.npad_id, parameters.applet_resource_user_id, | ||||
|              parameters.npad_joy_device_type); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1074,14 +1211,15 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.SetNpadMode(parameters.npad_id, {}, | ||||
|                                                Controller_NPad::NpadJoyAssignmentMode::Dual); | ||||
|  | ||||
|     LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, | ||||
|              parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1090,14 +1228,14 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { | ||||
|     const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; | ||||
|     const auto applet_resource_user_id{rp.Pop<u64>()}; | ||||
|  | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||||
|  | ||||
|     LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", | ||||
|               npad_id_1, npad_id_2, applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1157,19 +1295,14 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { | ||||
|     const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; | ||||
|     const auto applet_resource_user_id{rp.Pop<u64>()}; | ||||
|  | ||||
|     const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|                          .SwapNpadAssignment(npad_id_1, npad_id_2); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2); | ||||
|  | ||||
|     LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", | ||||
|               npad_id_1, npad_id_2, applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     if (res) { | ||||
|         rb.Push(ResultSuccess); | ||||
|     } else { | ||||
|         LOG_ERROR(Service_HID, "Npads are not connected!"); | ||||
|         rb.Push(NpadNotConnected); | ||||
|     } | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1183,13 +1316,17 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     bool is_enabled = false; | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = | ||||
|         controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled); | ||||
|  | ||||
|     LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", | ||||
|                 parameters.npad_id, parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|                 .IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id)); | ||||
|     rb.Push(result); | ||||
|     rb.Push(is_enabled); | ||||
| } | ||||
|  | ||||
| void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1204,9 +1341,9 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c | ||||
|  | ||||
|     const auto parameters{rp.PopRaw<Parameters>()}; | ||||
|  | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .SetUnintendedHomeButtonInputProtectionEnabled( | ||||
|             parameters.unintended_home_button_input_protection, parameters.npad_id); | ||||
|     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||
|     const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled( | ||||
|         parameters.unintended_home_button_input_protection, parameters.npad_id); | ||||
|  | ||||
|     LOG_WARNING(Service_HID, | ||||
|                 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," | ||||
| @@ -1215,7 +1352,7 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c | ||||
|                 parameters.applet_resource_user_id); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | ||||
| void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { | ||||
| @@ -1377,6 +1514,8 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto can_vibrate{rp.Pop<bool>()}; | ||||
|  | ||||
|     // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value | ||||
|     // by converting it to a bool | ||||
|     Settings::values.vibration_enabled.SetValue(can_vibrate); | ||||
|  | ||||
|     LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | ||||
| @@ -1388,9 +1527,12 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | ||||
| void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_HID, "called"); | ||||
|  | ||||
|     // nnSDK checks if a float is greater than zero. We return the bool we stored earlier | ||||
|     const auto is_enabled = Settings::values.vibration_enabled.GetValue(); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(Settings::values.vibration_enabled.GetValue()); | ||||
|     rb.Push(is_enabled); | ||||
| } | ||||
|  | ||||
| void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { | ||||
|   | ||||
| @@ -113,6 +113,11 @@ private: | ||||
|     void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | ||||
|     void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); | ||||
|     void IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx); | ||||
|     void EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx); | ||||
|     void IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx); | ||||
|     void LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx); | ||||
|     void GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx); | ||||
|     void ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx); | ||||
|     void ActivateGesture(Kernel::HLERequestContext& ctx); | ||||
|     void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | ||||
|     void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user