WiimoteReal: Make WiimoteScannerBackend classes use separate FindNewWiimotes and FindAttachedWiimotes functions.

Return results as vector of unique_ptr instead of raw pointers.
This commit is contained in:
Jordan Woyak 2025-10-04 17:30:44 -05:00
parent 99cc5e7bb7
commit 590b94975d
11 changed files with 84 additions and 57 deletions

View File

@ -22,11 +22,9 @@ namespace WiimoteReal
// Java classes
static jclass s_adapter_class;
void WiimoteScannerAndroid::FindWiimotes(std::vector<Wiimote*>& 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<Wiimote*>& 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)

View File

@ -49,7 +49,9 @@ public:
WiimoteScannerAndroid() = default;
~WiimoteScannerAndroid() override = default;
bool IsReady() const override { return true; }
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
FindResults FindAttachedWiimotes() override;
void Update() override {}
void RequestStopSearching() override {}
};

View File

@ -13,7 +13,6 @@ public:
WiimoteScannerDummy() = default;
~WiimoteScannerDummy() override = default;
bool IsReady() const override { return false; }
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override {}
void Update() override {}
void RequestStopSearching() override {}
};

View File

@ -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<Wiimote*>& found_wiimotes)
static auto GetAutoConnectAddresses()
{
std::vector<std::unique_ptr<Wiimote>> 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<Wiimote*>& found_wiimotes)
if (!IsNewWiimote(bt_address_str))
continue;
found_wiimotes.push_back(new WiimoteLinux(*bt_addr));
wii_remotes.emplace_back(std::make_unique<WiimoteLinux>(*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<Wiimote*>& 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<Wiimote*>& 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<Wiimote*>& found_wiimotes, Wi
BluetoothAddressToString(std::bit_cast<Common::BluetoothAddress>(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<Wiimote*>& found_wiimotes, Wi
std::make_unique<WiimoteLinux>(std::bit_cast<Common::BluetoothAddress>(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()

View File

@ -42,7 +42,10 @@ public:
~WiimoteScannerLinux() override;
bool IsReady() const override;
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
// FYI: This backend only supports connecting remotes just found via Bluetooth inquiry.
FindResults FindNewWiimotes() override;
void Update() override;
void RequestStopSearching() override;

View File

@ -576,9 +576,10 @@ int WiimoteWindows::IOWrite(const u8* buf, size_t len)
return write_result;
}
void WiimoteScannerWindows::FindWiimoteHIDDevices(std::vector<Wiimote*>& 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<Wiimote*>& 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<Wiimote*>& 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*>&, 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<Wiimote*>& found_wiimotes,
Wiimote*& found_board)
auto WiimoteScannerWindows::FindAttachedWiimotes() -> FindResults
{
FindWiimoteHIDDevices(found_wiimotes, found_board);
return FindWiimoteHIDDevices();
}
bool WiimoteScannerWindows::IsReady() const

View File

@ -52,8 +52,10 @@ class WiimoteScannerWindows final : public WiimoteScannerBackend
public:
WiimoteScannerWindows();
bool IsReady() const override;
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
void FindAttachedDevices(std::vector<Wiimote*>&, 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*>&, Wiimote*&);
FindResults FindWiimoteHIDDevices();
};
} // namespace WiimoteReal

View File

@ -108,8 +108,10 @@ bool WiimoteScannerHidapi::IsReady() const
return true;
}
void WiimoteScannerHidapi::FindWiimotes(std::vector<Wiimote*>& 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<Wiimote*>& wiimotes, Wiimote
LogLinuxDriverName(device->path);
#endif
auto* wiimote = new WiimoteHidapi(device->path);
auto wiimote = std::make_unique<WiimoteHidapi>(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<Wiimote*>& 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))

View File

@ -36,7 +36,9 @@ public:
WiimoteScannerHidapi();
~WiimoteScannerHidapi() override;
bool IsReady() const override;
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
FindResults FindAttachedWiimotes() override;
void Update() override {} // not needed for hidapi
void RequestStopSearching() override {} // not needed for hidapi
};

View File

@ -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<Wiimote*> 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>(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<Wiimote>(found_board));
TryToConnectBalanceBoard(std::move(bboard));
}
}
}

View File

@ -184,15 +184,24 @@ public:
// Note: Invoked from UI thread.
virtual bool IsReady() const = 0;
virtual void FindWiimotes(std::vector<Wiimote*>&, 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*>&, Wiimote*&) {}
struct FindResults
{
std::vector<std::unique_ptr<Wiimote>> wii_remotes;
std::vector<std::unique_ptr<Wiimote>> 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