From cd18c7405274f59190b5b1885db007b2834d73ec Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Tue, 3 Dec 2024 16:36:42 +0000 Subject: [PATCH] Prevent connection attempts on still-connected controllers --- src/gui/PairingDialog.cpp | 2 +- src/input/api/Wiimote/l2cap/L2CapWiimote.cpp | 94 +++++++++++--------- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/gui/PairingDialog.cpp b/src/gui/PairingDialog.cpp index 00af61bce..6d9bf9384 100644 --- a/src/gui/PairingDialog.cpp +++ b/src/gui/PairingDialog.cpp @@ -245,7 +245,7 @@ void PairingDialog::WorkerThread() // Search for device inquiry_info* infos = nullptr; m_cancelButton->Disable(); - const auto respCount = hci_inquiry(hostId, 5, 4, LIAC_LAP, &infos, IREQ_CACHE_FLUSH); + const auto respCount = hci_inquiry(hostId, 7, 4, LIAC_LAP, &infos, IREQ_CACHE_FLUSH); m_cancelButton->Enable(); if (respCount <= 0) { diff --git a/src/input/api/Wiimote/l2cap/L2CapWiimote.cpp b/src/input/api/Wiimote/l2cap/L2CapWiimote.cpp index 351c279f6..28a123f35 100644 --- a/src/input/api/Wiimote/l2cap/L2CapWiimote.cpp +++ b/src/input/api/Wiimote/l2cap/L2CapWiimote.cpp @@ -1,63 +1,70 @@ #include "L2CapWiimote.h" #include -namespace { - std::vector s_address; - std::mutex s_addressMutex; +constexpr auto comparator = [](const bdaddr_t& a, const bdaddr_t& b) { + return bacmp(&a, &b); +}; - bool AttemptConnect(int& sockFd, const sockaddr_l2& addr) - { - auto res = connect(sockFd, reinterpret_cast(&addr), - sizeof(sockaddr_l2)); - if (res == 0) - return true; - if (res != ECONNREFUSED) - return false; - return connect(sockFd, reinterpret_cast(&addr), - sizeof(sockaddr_l2)) == 0; - } - bool AttemptSetNonBlock(int& sockFd) - { - return fcntl(sockFd, F_SETFL, fcntl(sockFd, F_GETFL) | O_NONBLOCK) == 0; - } -} +static auto s_addresses = std::map(comparator); +static std::mutex s_addressMutex; -static bool operator==(const bdaddr_t& a, const bdaddr_t& b) +static bool AttemptConnect(int sockFd, const sockaddr_l2& addr) { - return bacmp(&a, &b) == 0; + auto res = connect(sockFd, reinterpret_cast(&addr), + sizeof(sockaddr_l2)); + if (res == 0) + return true; + return connect(sockFd, reinterpret_cast(&addr), + sizeof(sockaddr_l2)) == 0; } -L2CapWiimote::L2CapWiimote(int recvFd,int sendFd, bdaddr_t addr) -: m_recvFd(recvFd), m_sendFd(sendFd), m_addr(addr) +static bool AttemptSetNonBlock(int sockFd) { + return fcntl(sockFd, F_SETFL, fcntl(sockFd, F_GETFL) | O_NONBLOCK) == 0; +} +L2CapWiimote::L2CapWiimote(int recvFd, int sendFd, bdaddr_t addr) + : m_recvFd(recvFd), m_sendFd(sendFd), m_addr(addr) +{ } L2CapWiimote::~L2CapWiimote() { - ::close(m_recvFd); - ::close(m_sendFd); + close(m_recvFd); + close(m_sendFd); + const auto& b = m_addr.b; + cemuLog_logDebug(LogType::Force, "Wiimote at {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x} disconnected", b[5], b[4], b[3], b[2], b[1], b[0]); + + // Re-add to candidate vec + s_addressMutex.lock(); + s_addresses[m_addr] = false; + s_addressMutex.unlock(); } void L2CapWiimote::AddCandidateAddress(bdaddr_t addr) { std::scoped_lock lock(s_addressMutex); - vectorAppendUnique(s_address,addr); + s_addresses.try_emplace(addr, false); } std::vector L2CapWiimote::get_devices() { s_addressMutex.lock(); - const auto addresses = s_address; + std::vector unconnected; + for (const auto& [addr, connected] : s_addresses) + { + if (!connected) + unconnected.push_back(addr); + } s_addressMutex.unlock(); - std::vector outDevices; - for (auto addr : addresses) + for (const auto& addr : unconnected) { // Socket for sending data to controller, PSM 0x11 auto sendFd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - if (sendFd < 0) { + if (sendFd < 0) + { cemuLog_logDebug(LogType::Force, "Failed to open send socket: {}", strerror(errno)); continue; } @@ -67,18 +74,20 @@ std::vector L2CapWiimote::get_devices() sendAddr.l2_psm = htobs(0x11); sendAddr.l2_bdaddr = addr; - if (!AttemptConnect(sendFd, sendAddr) || !AttemptSetNonBlock(sendFd)) { + if (!AttemptConnect(sendFd, sendAddr) || !AttemptSetNonBlock(sendFd)) + { const auto& b = addr.b; - cemuLog_logDebug(LogType::Force,"Failed to connect send socket to '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}': {}", - b[5], b[4], b[3], b[2], b[1], b[0], strerror(errno)); + cemuLog_logDebug(LogType::Force, "Failed to connect send socket to '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}': {}", + b[5], b[4], b[3], b[2], b[1], b[0], strerror(errno)); close(sendFd); continue; } // Socket for receiving data from controller, PSM 0x13 auto recvFd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - if (recvFd < 0) { - cemuLog_logDebug(LogType::Force,"Failed to open recv socket: {}", strerror(errno)); + if (recvFd < 0) + { + cemuLog_logDebug(LogType::Force, "Failed to open recv socket: {}", strerror(errno)); close(sendFd); continue; } @@ -87,16 +96,20 @@ std::vector L2CapWiimote::get_devices() recvAddr.l2_psm = htobs(0x13); recvAddr.l2_bdaddr = addr; - if (!AttemptConnect(recvFd, recvAddr) || !AttemptSetNonBlock(recvFd)) { + if (!AttemptConnect(recvFd, recvAddr) || !AttemptSetNonBlock(recvFd)) + { const auto& b = addr.b; - cemuLog_logDebug(LogType::Force,"Failed to connect recv socket to '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}': {}", - b[5], b[4], b[3], b[2], b[1], b[0], strerror(errno)); + cemuLog_logDebug(LogType::Force, "Failed to connect recv socket to '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}': {}", + b[5], b[4], b[3], b[2], b[1], b[0], strerror(errno)); close(sendFd); close(recvFd); continue; } - outDevices.emplace_back(std::make_shared(sendFd, recvFd, addr)); + + s_addressMutex.lock(); + s_addresses[addr] = true; + s_addressMutex.unlock(); } return outDevices; } @@ -126,11 +139,10 @@ std::optional> L2CapWiimote::read_data() return std::vector(buffer + 1, buffer + 1 + nBytes - 1); } - bool L2CapWiimote::operator==(const WiimoteDevice& rhs) const { auto mote = dynamic_cast(&rhs); if (!mote) return false; - return m_addr == mote->m_addr; + return bacmp(&m_addr, &mote->m_addr) == 0; } \ No newline at end of file