From 590b94975d23e03612c229fb7450e75b80daa17f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 4 Oct 2025 17:30:44 -0500 Subject: [PATCH] WiimoteReal: Make WiimoteScannerBackend classes use separate FindNewWiimotes and FindAttachedWiimotes functions. Return results as vector of unique_ptr instead of raw pointers. --- Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp | 13 +++++---- Source/Core/Core/HW/WiimoteReal/IOAndroid.h | 4 ++- Source/Core/Core/HW/WiimoteReal/IODummy.h | 1 - Source/Core/Core/HW/WiimoteReal/IOLinux.cpp | 28 +++++++++++-------- Source/Core/Core/HW/WiimoteReal/IOLinux.h | 5 +++- Source/Core/Core/HW/WiimoteReal/IOWin.cpp | 23 +++++++-------- Source/Core/Core/HW/WiimoteReal/IOWin.h | 8 ++++-- Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp | 12 +++++--- Source/Core/Core/HW/WiimoteReal/IOhidapi.h | 4 ++- .../Core/Core/HW/WiimoteReal/WiimoteReal.cpp | 26 ++++++++--------- Source/Core/Core/HW/WiimoteReal/WiimoteReal.h | 17 ++++++++--- 11 files changed, 84 insertions(+), 57 deletions(-) diff --git a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp index e5e511c6945..bdc0a6fc424 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp @@ -22,11 +22,9 @@ namespace WiimoteReal // Java classes static jclass s_adapter_class; -void WiimoteScannerAndroid::FindWiimotes(std::vector& found_wiimotes, - Wiimote*& found_board) +auto WiimoteScannerAndroid::FindAttachedWiimotes() -> FindResults { - found_wiimotes.clear(); - found_board = nullptr; + FindResults results; NOTICE_LOG_FMT(WIIMOTE, "Finding Wiimotes"); @@ -48,9 +46,14 @@ void WiimoteScannerAndroid::FindWiimotes(std::vector& found_wiimotes, if (!wiimote->ConnectInternal()) continue; - found_wiimotes.emplace_back(wiimote.release()); + // TODO: We make no attempt to differentiate balance boards here. + // wiimote->IsBalanceBoard() would probably be enough to do that. + + results.wii_remotes.emplace_back(std::move(wiimote)); } } + + return results; } WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index) diff --git a/Source/Core/Core/HW/WiimoteReal/IOAndroid.h b/Source/Core/Core/HW/WiimoteReal/IOAndroid.h index 506c9ae5c1e..fc257a8ad63 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOAndroid.h +++ b/Source/Core/Core/HW/WiimoteReal/IOAndroid.h @@ -49,7 +49,9 @@ public: WiimoteScannerAndroid() = default; ~WiimoteScannerAndroid() override = default; bool IsReady() const override { return true; } - void FindWiimotes(std::vector&, Wiimote*&) override; + + FindResults FindAttachedWiimotes() override; + void Update() override {} void RequestStopSearching() override {} }; diff --git a/Source/Core/Core/HW/WiimoteReal/IODummy.h b/Source/Core/Core/HW/WiimoteReal/IODummy.h index 2df8e6fb5c0..2fe6e9a71f2 100644 --- a/Source/Core/Core/HW/WiimoteReal/IODummy.h +++ b/Source/Core/Core/HW/WiimoteReal/IODummy.h @@ -13,7 +13,6 @@ public: WiimoteScannerDummy() = default; ~WiimoteScannerDummy() override = default; bool IsReady() const override { return false; } - void FindWiimotes(std::vector&, Wiimote*&) override {} void Update() override {} void RequestStopSearching() override {} }; diff --git a/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp b/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp index 3fe5f09403a..5f1f6c68904 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp @@ -31,8 +31,10 @@ namespace WiimoteReal constexpr u16 L2CAP_PSM_HID_CNTL = 0x0011; constexpr u16 L2CAP_PSM_HID_INTR = 0x0013; -static void AddAutoConnectAddresses(std::vector& found_wiimotes) +static auto GetAutoConnectAddresses() { + std::vector> wii_remotes; + std::string entries = Config::Get(Config::MAIN_WIIMOTE_AUTO_CONNECT_ADDRESSES); for (auto& bt_address_str : SplitString(entries, ',')) { @@ -47,9 +49,11 @@ static void AddAutoConnectAddresses(std::vector& found_wiimotes) if (!IsNewWiimote(bt_address_str)) continue; - found_wiimotes.push_back(new WiimoteLinux(*bt_addr)); + wii_remotes.emplace_back(std::make_unique(*bt_addr)); NOTICE_LOG_FMT(WIIMOTE, "Added Wiimote with fixed address ({}).", bt_address_str); } + + return wii_remotes; } WiimoteScannerLinux::WiimoteScannerLinux() @@ -157,14 +161,14 @@ static int HciInquiry(int device_socket, InquiryRequest* request) return hci_inquiry_errorno; } -void WiimoteScannerLinux::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) +auto WiimoteScannerLinux::FindNewWiimotes() -> FindResults { - found_board = nullptr; + FindResults results; if (!Open()) - return; + return results; - AddAutoConnectAddresses(found_wiimotes); + results.wii_remotes = GetAutoConnectAddresses(); InquiryRequest request{}; request.dev_id = m_device_id; @@ -186,7 +190,7 @@ void WiimoteScannerLinux::FindWiimotes(std::vector& found_wiimotes, Wi default: ERROR_LOG_FMT(WIIMOTE, "Error searching for Bluetooth devices: {}", Common::StrerrorString(hci_inquiry_result)); - return; + return results; } DEBUG_LOG_FMT(WIIMOTE, "Found {} Bluetooth device(s).", request.num_rsp); @@ -197,8 +201,8 @@ void WiimoteScannerLinux::FindWiimotes(std::vector& found_wiimotes, Wi BluetoothAddressToString(std::bit_cast(scan_info.bdaddr)); // Did AddAutoConnectAddresses already add this remote? - const auto eq_this_bdaddr = [&](auto* wm) { return wm->GetId() == bdaddr_str; }; - if (std::ranges::any_of(found_wiimotes, eq_this_bdaddr)) + const auto eq_this_bdaddr = [&](auto& wm) { return wm->GetId() == bdaddr_str; }; + if (std::ranges::any_of(results.wii_remotes, eq_this_bdaddr)) continue; if (!IsNewWiimote(bdaddr_str)) @@ -233,15 +237,17 @@ void WiimoteScannerLinux::FindWiimotes(std::vector& found_wiimotes, Wi std::make_unique(std::bit_cast(scan_info.bdaddr)); if (IsBalanceBoardName(name)) { - delete std::exchange(found_board, wm.release()); + results.balance_boards.emplace_back(std::move(wm)); NOTICE_LOG_FMT(WIIMOTE, "Found balance board ({}).", bdaddr_str); } else { - found_wiimotes.push_back(wm.release()); + results.wii_remotes.emplace_back(std::move(wm)); NOTICE_LOG_FMT(WIIMOTE, "Found Wiimote ({}).", bdaddr_str); } } + + return results; } void WiimoteScannerLinux::Update() diff --git a/Source/Core/Core/HW/WiimoteReal/IOLinux.h b/Source/Core/Core/HW/WiimoteReal/IOLinux.h index 9f03dbd066b..7f88ac89b8c 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOLinux.h +++ b/Source/Core/Core/HW/WiimoteReal/IOLinux.h @@ -42,7 +42,10 @@ public: ~WiimoteScannerLinux() override; bool IsReady() const override; - void FindWiimotes(std::vector&, Wiimote*&) override; + + // FYI: This backend only supports connecting remotes just found via Bluetooth inquiry. + FindResults FindNewWiimotes() override; + void Update() override; void RequestStopSearching() override; diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index 91ed7d8d561..af442355cd4 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -576,9 +576,10 @@ int WiimoteWindows::IOWrite(const u8* buf, size_t len) return write_result; } -void WiimoteScannerWindows::FindWiimoteHIDDevices(std::vector& found_wiimotes, - Wiimote*& found_board) +auto WiimoteScannerWindows::FindWiimoteHIDDevices() -> FindResults { + FindResults results; + // Enumerate connected HID interfaces IDs. auto class_guid = GUID_DEVINTERFACE_HID; constexpr ULONG flags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT; @@ -591,7 +592,7 @@ void WiimoteScannerWindows::FindWiimoteHIDDevices(std::vector& found_w if (list_result != CR_SUCCESS) { ERROR_LOG_FMT(WIIMOTE, "CM_Get_Device_Interface_List: {}", list_result); - return; + return results; } for (const WCHAR* hid_iface = buffer.get(); *hid_iface != L'\0'; @@ -678,26 +679,26 @@ void WiimoteScannerWindows::FindWiimoteHIDDevices(std::vector& found_w is_balance_board = wiimote->IsBalanceBoard(); if (*is_balance_board) - delete std::exchange(found_board, wiimote.release()); + results.balance_boards.emplace_back(std::move(wiimote)); else - found_wiimotes.push_back(wiimote.release()); + results.wii_remotes.emplace_back(std::move(wiimote)); } + + return results; } -void WiimoteScannerWindows::FindWiimotes(std::vector&, Wiimote*&) +auto WiimoteScannerWindows::FindNewWiimotes() -> FindResults { // Ideally we'd only enumerate the radios once. RemoveUnusableWiimoteBluetoothDevices(); DiscoverAndPairWiimotes(DEFAULT_INQUIRY_LENGTH); - // Kinda odd that we never return any remotes here. The scanner interface is odd. - // We return all the results in FindAlreadyConnectedWiimote. + return FindWiimoteHIDDevices(); } -void WiimoteScannerWindows::FindAttachedDevices(std::vector& found_wiimotes, - Wiimote*& found_board) +auto WiimoteScannerWindows::FindAttachedWiimotes() -> FindResults { - FindWiimoteHIDDevices(found_wiimotes, found_board); + return FindWiimoteHIDDevices(); } bool WiimoteScannerWindows::IsReady() const diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.h b/Source/Core/Core/HW/WiimoteReal/IOWin.h index 12c577f950e..b8bc29a86fe 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.h +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.h @@ -52,8 +52,10 @@ class WiimoteScannerWindows final : public WiimoteScannerBackend public: WiimoteScannerWindows(); bool IsReady() const override; - void FindWiimotes(std::vector&, Wiimote*&) override; - void FindAttachedDevices(std::vector&, Wiimote*&) override; + + FindResults FindNewWiimotes() override; + FindResults FindAttachedWiimotes() override; + void Update() override; void RequestStopSearching() override {} @@ -61,7 +63,7 @@ public: static void RemoveRememberedWiimotes(); private: - void FindWiimoteHIDDevices(std::vector&, Wiimote*&); + FindResults FindWiimoteHIDDevices(); }; } // namespace WiimoteReal diff --git a/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp b/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp index 7a70b09409b..4f38c4a9499 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp @@ -108,8 +108,10 @@ bool WiimoteScannerHidapi::IsReady() const return true; } -void WiimoteScannerHidapi::FindWiimotes(std::vector& wiimotes, Wiimote*& board) +auto WiimoteScannerHidapi::FindAttachedWiimotes() -> FindResults { + FindResults results; + hid_device_info* list = hid_enumerate(0x0, 0x0); // FYI: 0 for all VID/PID. for (hid_device_info* device = list; device != nullptr; device = device->next) { @@ -123,12 +125,12 @@ void WiimoteScannerHidapi::FindWiimotes(std::vector& wiimotes, Wiimote LogLinuxDriverName(device->path); #endif - auto* wiimote = new WiimoteHidapi(device->path); + auto wiimote = std::make_unique(device->path); const bool is_balance_board = IsBalanceBoardName(name) || wiimote->IsBalanceBoard(); if (is_balance_board) - board = wiimote; + results.balance_boards.emplace_back(std::move(wiimote)); else - wiimotes.push_back(wiimote); + results.wii_remotes.emplace_back(std::move(wiimote)); NOTICE_LOG_FMT(WIIMOTE, "Found {} at {}: {} {} ({:04x}:{:04x})", is_balance_board ? "balance board" : "Wiimote", device->path, @@ -136,6 +138,8 @@ void WiimoteScannerHidapi::FindWiimotes(std::vector& wiimotes, Wiimote WStringToUTF8(device->product_string), device->vendor_id, device->product_id); } hid_free_enumeration(list); + + return results; } WiimoteHidapi::WiimoteHidapi(std::string device_path) : m_device_path(std::move(device_path)) diff --git a/Source/Core/Core/HW/WiimoteReal/IOhidapi.h b/Source/Core/Core/HW/WiimoteReal/IOhidapi.h index f4340e3bc28..16cb6c858db 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOhidapi.h +++ b/Source/Core/Core/HW/WiimoteReal/IOhidapi.h @@ -36,7 +36,9 @@ public: WiimoteScannerHidapi(); ~WiimoteScannerHidapi() override; bool IsReady() const override; - void FindWiimotes(std::vector&, Wiimote*&) override; + + FindResults FindAttachedWiimotes() override; + void Update() override {} // not needed for hidapi void RequestStopSearching() override {} // not needed for hidapi }; diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index 7451c5d02b6..e21017ec7b3 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -716,40 +716,36 @@ void WiimoteScanner::ThreadFunc() auto scan_mode = WiimoteScanMode::SCAN_ONCE; m_scan_mode.compare_exchange_strong(scan_mode, WiimoteScanMode::DO_NOT_SCAN); + // When not scanning we still look for already attached devices. + // This allows Windows, hidapi, and DolphinBar remotes to be quickly discovered. + const bool should_perform_inquiry = scan_mode != WiimoteScanMode::DO_NOT_SCAN; + for (const auto& backend : m_backends) { - std::vector found_wiimotes; - Wiimote* found_board = nullptr; - - // When not scanning we still look for already attached devices. - // This allows Windows and DolphinBar remotes to be quickly discovered. - if (scan_mode == WiimoteScanMode::DO_NOT_SCAN) - backend->FindAttachedDevices(found_wiimotes, found_board); - else - backend->FindWiimotes(found_wiimotes, found_board); - + auto results = + should_perform_inquiry ? backend->FindNewWiimotes() : backend->FindAttachedWiimotes(); { std::unique_lock wm_lk(g_wiimotes_mutex); - for (auto* wiimote : found_wiimotes) + for (auto& wiimote : results.wii_remotes) { { std::lock_guard lk(s_known_ids_mutex); s_known_ids.insert(wiimote->GetId()); } - AddWiimoteToPool(std::unique_ptr(wiimote)); + AddWiimoteToPool(std::move(wiimote)); g_controller_interface.PlatformPopulateDevices([] { ProcessWiimotePool(); }); } - if (found_board) + for (auto& bboard : results.balance_boards) { { std::lock_guard lk(s_known_ids_mutex); - s_known_ids.insert(found_board->GetId()); + s_known_ids.insert(bboard->GetId()); } - TryToConnectBalanceBoard(std::unique_ptr(found_board)); + TryToConnectBalanceBoard(std::move(bboard)); } } } diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index dd0f699aed9..940eedeab16 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -184,15 +184,24 @@ public: // Note: Invoked from UI thread. virtual bool IsReady() const = 0; - virtual void FindWiimotes(std::vector&, Wiimote*&) = 0; // function called when not looking for more Wiimotes virtual void Update() = 0; // requests the backend to stop scanning if FindWiimotes is blocking virtual void RequestStopSearching() = 0; - // Used by Windows to search for HID interfaces of already connected Wii remotes. - // hidapi should probably implement the equivalent. - virtual void FindAttachedDevices(std::vector&, Wiimote*&) {} + struct FindResults + { + std::vector> wii_remotes; + std::vector> balance_boards; + }; + + // Implementations are expected to perform a new inquiry if possible. + // Only not-yet-in-use remotes shall be returned. + virtual FindResults FindNewWiimotes() { return FindAttachedWiimotes(); } + + // Implementations shall return not-not-in-use already connected remotes. + // e.g. DolphinBar interfaces would be found here. + virtual FindResults FindAttachedWiimotes() { return {}; } }; enum class WiimoteScanMode