From 4d308fd0b4fc8f14754c47811e751bf068b330b8 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 18 Oct 2021 23:15:46 -0500 Subject: hid: Fix controller connection/disconnection --- .../service/hid/controllers/controller_base.cpp | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 77 +++++++++++++++------- src/core/hle/service/hid/controllers/npad.h | 3 + 3 files changed, 56 insertions(+), 26 deletions(-) (limited to 'src/core/hle/service/hid/controllers') diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index 9d1e6db6a..74a394784 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp @@ -11,7 +11,7 @@ ControllerBase::~ControllerBase() = default; void ControllerBase::ActivateController() { if (is_activated) { - OnRelease(); + return; } is_activated = true; OnInit(); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a2e9ddf4d..144abab65 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -125,18 +125,22 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, return; } + auto& controller = controller_data[controller_idx]; + const auto is_connected = controller.device->IsConnected(); + const auto npad_type = controller.device->GetNpadType(); switch (type) { case Core::HID::ControllerTriggerType::Connected: - InitNewlyAddedController(controller_idx); - break; case Core::HID::ControllerTriggerType::Disconnected: - DisconnectNpadAtIndex(controller_idx); + if (is_connected == controller.is_connected) { + return; + } + UpdateControllerAt(npad_type, controller_idx, is_connected); break; case Core::HID::ControllerTriggerType::Type: { - auto& controller = controller_data[controller_idx]; - if (controller.device->IsConnected()) { - LOG_ERROR(Service_HID, "Controller type changed without turning off the controller"); + if (npad_type == controller.npad_type) { + return; } + // UpdateControllerAt(npad_type, controller_idx, is_connected); break; } default: @@ -146,6 +150,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { auto& controller = controller_data[controller_idx]; + LOG_ERROR(Service_HID, "Connect {} {}", controller_idx, controller.is_connected); const auto controller_type = controller.device->GetNpadType(); auto& shared_memory = controller.shared_memory_entry; if (controller_type == Core::HID::NpadType::None) { @@ -235,20 +240,23 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.battery_level_left = battery_level.left.battery_level; shared_memory.battery_level_right = battery_level.right.battery_level; + controller.is_connected = true; + controller.device->Connect(); SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); + WriteEmptyEntry(controller.shared_memory_entry); } void Controller_NPad::OnInit() { + if (!IsControllerActivated()) { + return; + } + for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; controller.styleset_changed_event = service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); } - if (!IsControllerActivated()) { - return; - } - if (system.HIDCore().GetSupportedStyleTag().raw == 0) { // We want to support all controllers Core::HID::NpadStyleTag style{}; @@ -277,20 +285,33 @@ void Controller_NPad::OnInit() { for (auto& controller : controller_data) { NPadGenericState dummy_pad_state{}; auto& npad = controller.shared_memory_entry; - for (std::size_t i = 0; i < 17; ++i) { - dummy_pad_state.sampling_number = - npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; - npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); - npad.handheld_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); - npad.palma_lifo.WriteNextEntry(dummy_pad_state); + for (std::size_t i = 0; i < 19; ++i) { + WriteEmptyEntry(npad); } } } +void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) { + NPadGenericState dummy_pad_state{}; + NpadGcTriggerState dummy_gc_state{}; + dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; + npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1; + npad.handheld_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; + npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1; + npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1; + npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1; + npad.palma_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1; + npad.system_ext_lifo.WriteNextEntry(dummy_pad_state); + dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; + npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state); +} + void Controller_NPad::OnRelease() { for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; @@ -359,6 +380,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { return; } + for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; auto& npad = controller.shared_memory_entry; @@ -366,6 +388,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* const auto& controller_type = controller.device->GetNpadType(); if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { + // Refresh shared memory + std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), + &controller.shared_memory_entry, sizeof(NpadInternalState)); continue; } const u32 npad_index = static_cast(i); @@ -830,14 +855,14 @@ void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::si void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index, bool connected) { - auto& controller = controller_data[npad_index].device; + auto& controller = controller_data[npad_index]; if (!connected) { DisconnectNpadAtIndex(npad_index); return; } - controller->SetNpadType(type); - controller->Connect(); + controller.device->SetNpadType(type); + controller.device->Connect(); InitNewlyAddedController(npad_index); } @@ -847,14 +872,13 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { auto& controller = controller_data[npad_index]; + LOG_ERROR(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected); for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { // Send an empty vibration to stop any vibrations. VibrateControllerAtIndex(npad_index, device_idx, {}); controller.vibration[device_idx].device_mounted = false; } - controller.device->Disconnect(); - auto& shared_memory_entry = controller.shared_memory_entry; shared_memory_entry.style_set.raw = 0; // Zero out shared_memory_entry.device_type.raw = 0; @@ -868,7 +892,10 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory_entry.footer_type = AppletFooterUiType::None; + controller.is_connected = false; + controller.device->Disconnect(); SignalStyleSetChangedEvent(IndexToNPad(npad_index)); + WriteEmptyEntry(controller.shared_memory_entry); } void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index b0e2f8430..d805ccb97 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -417,6 +417,8 @@ private: std::array vibration{}; bool unintended_home_button_input_protection{}; + bool is_connected{}; + Core::HID::NpadType npad_type{Core::HID::NpadType::None}; // Current pad state NPadGenericState npad_pad_state{}; @@ -435,6 +437,7 @@ private: void InitNewlyAddedController(std::size_t controller_idx); bool IsControllerSupported(Core::HID::NpadType controller) const; void RequestPadStateUpdate(u32 npad_id); + void WriteEmptyEntry(NpadInternalState& npad); std::atomic press_state{}; -- cgit v1.2.3