diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 648 |
1 files changed, 349 insertions, 299 deletions
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 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; + } + + const auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle); + is_firmware_available = sixaxis_properties.is_firmware_update_available != 0; + return ResultSuccess; +} + +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; } - // We don't support joycon firmware updates - is_firmware_available = false; + // 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::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, +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) { - 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; } + 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; - } - - 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; + return NpadIsSameType; + } + + // 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 |