Prevent connection attempts on still-connected controllers

This commit is contained in:
capitalistspz 2024-12-03 16:36:42 +00:00
parent 08b0bfba8b
commit a648fc7a08
2 changed files with 54 additions and 42 deletions

View file

@ -245,7 +245,7 @@ void PairingDialog::WorkerThread()
// Search for device // Search for device
inquiry_info* infos = nullptr; inquiry_info* infos = nullptr;
m_cancelButton->Disable(); 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(); m_cancelButton->Enable();
if (respCount <= 0) if (respCount <= 0)
{ {

View file

@ -1,63 +1,70 @@
#include "L2CapWiimote.h" #include "L2CapWiimote.h"
#include <bluetooth/l2cap.h> #include <bluetooth/l2cap.h>
namespace { constexpr auto comparator = [](const bdaddr_t& a, const bdaddr_t& b) {
std::vector<bdaddr_t> s_address; return bacmp(&a, &b);
std::mutex s_addressMutex; };
bool AttemptConnect(int& sockFd, const sockaddr_l2& addr) static auto s_addresses = std::map<bdaddr_t, bool, decltype(comparator)>(comparator);
{ static std::mutex s_addressMutex;
static bool AttemptConnect(int sockFd, const sockaddr_l2& addr)
{
auto res = connect(sockFd, reinterpret_cast<const sockaddr*>(&addr), auto res = connect(sockFd, reinterpret_cast<const sockaddr*>(&addr),
sizeof(sockaddr_l2)); sizeof(sockaddr_l2));
if (res == 0) if (res == 0)
return true; return true;
if (res != ECONNREFUSED)
return false;
return connect(sockFd, reinterpret_cast<const sockaddr*>(&addr), return connect(sockFd, reinterpret_cast<const sockaddr*>(&addr),
sizeof(sockaddr_l2)) == 0; sizeof(sockaddr_l2)) == 0;
} }
bool AttemptSetNonBlock(int& sockFd)
{ static bool AttemptSetNonBlock(int sockFd)
{
return fcntl(sockFd, F_SETFL, fcntl(sockFd, F_GETFL) | O_NONBLOCK) == 0; return fcntl(sockFd, F_SETFL, fcntl(sockFd, F_GETFL) | O_NONBLOCK) == 0;
}
} }
static bool operator==(const bdaddr_t& a, const bdaddr_t& b) L2CapWiimote::L2CapWiimote(int recvFd, int sendFd, bdaddr_t addr)
: m_recvFd(recvFd), m_sendFd(sendFd), m_addr(addr)
{ {
return bacmp(&a, &b) == 0;
}
L2CapWiimote::L2CapWiimote(int recvFd,int sendFd, bdaddr_t addr)
: m_recvFd(recvFd), m_sendFd(sendFd), m_addr(addr)
{
} }
L2CapWiimote::~L2CapWiimote() L2CapWiimote::~L2CapWiimote()
{ {
::close(m_recvFd); close(m_recvFd);
::close(m_sendFd); 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) void L2CapWiimote::AddCandidateAddress(bdaddr_t addr)
{ {
std::scoped_lock lock(s_addressMutex); std::scoped_lock lock(s_addressMutex);
vectorAppendUnique(s_address,addr); s_addresses.try_emplace(addr, false);
} }
std::vector<WiimoteDevicePtr> L2CapWiimote::get_devices() std::vector<WiimoteDevicePtr> L2CapWiimote::get_devices()
{ {
s_addressMutex.lock(); s_addressMutex.lock();
const auto addresses = s_address; std::vector<bdaddr_t> unconnected;
for (const auto& [addr, connected] : s_addresses)
{
if (!connected)
unconnected.push_back(addr);
}
s_addressMutex.unlock(); s_addressMutex.unlock();
std::vector<WiimoteDevicePtr> outDevices; std::vector<WiimoteDevicePtr> outDevices;
for (auto addr : addresses) for (const auto& addr : unconnected)
{ {
// Socket for sending data to controller, PSM 0x11 // Socket for sending data to controller, PSM 0x11
auto sendFd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 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)); cemuLog_logDebug(LogType::Force, "Failed to open send socket: {}", strerror(errno));
continue; continue;
} }
@ -67,9 +74,10 @@ std::vector<WiimoteDevicePtr> L2CapWiimote::get_devices()
sendAddr.l2_psm = htobs(0x11); sendAddr.l2_psm = htobs(0x11);
sendAddr.l2_bdaddr = addr; sendAddr.l2_bdaddr = addr;
if (!AttemptConnect(sendFd, sendAddr) || !AttemptSetNonBlock(sendFd)) { if (!AttemptConnect(sendFd, sendAddr) || !AttemptSetNonBlock(sendFd))
{
const auto& b = addr.b; const auto& b = addr.b;
cemuLog_logDebug(LogType::Force,"Failed to connect send socket to '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}': {}", 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)); b[5], b[4], b[3], b[2], b[1], b[0], strerror(errno));
close(sendFd); close(sendFd);
continue; continue;
@ -77,8 +85,9 @@ std::vector<WiimoteDevicePtr> L2CapWiimote::get_devices()
// Socket for receiving data from controller, PSM 0x13 // Socket for receiving data from controller, PSM 0x13
auto recvFd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); auto recvFd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
if (recvFd < 0) { if (recvFd < 0)
cemuLog_logDebug(LogType::Force,"Failed to open recv socket: {}", strerror(errno)); {
cemuLog_logDebug(LogType::Force, "Failed to open recv socket: {}", strerror(errno));
close(sendFd); close(sendFd);
continue; continue;
} }
@ -87,16 +96,20 @@ std::vector<WiimoteDevicePtr> L2CapWiimote::get_devices()
recvAddr.l2_psm = htobs(0x13); recvAddr.l2_psm = htobs(0x13);
recvAddr.l2_bdaddr = addr; recvAddr.l2_bdaddr = addr;
if (!AttemptConnect(recvFd, recvAddr) || !AttemptSetNonBlock(recvFd)) { if (!AttemptConnect(recvFd, recvAddr) || !AttemptSetNonBlock(recvFd))
{
const auto& b = addr.b; const auto& b = addr.b;
cemuLog_logDebug(LogType::Force,"Failed to connect recv socket to '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}': {}", 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)); b[5], b[4], b[3], b[2], b[1], b[0], strerror(errno));
close(sendFd); close(sendFd);
close(recvFd); close(recvFd);
continue; continue;
} }
outDevices.emplace_back(std::make_shared<L2CapWiimote>(sendFd, recvFd, addr)); outDevices.emplace_back(std::make_shared<L2CapWiimote>(sendFd, recvFd, addr));
s_addressMutex.lock();
s_addresses[addr] = true;
s_addressMutex.unlock();
} }
return outDevices; return outDevices;
} }
@ -126,11 +139,10 @@ std::optional<std::vector<uint8>> L2CapWiimote::read_data()
return std::vector(buffer + 1, buffer + 1 + nBytes - 1); return std::vector(buffer + 1, buffer + 1 + nBytes - 1);
} }
bool L2CapWiimote::operator==(const WiimoteDevice& rhs) const bool L2CapWiimote::operator==(const WiimoteDevice& rhs) const
{ {
auto mote = dynamic_cast<const L2CapWiimote*>(&rhs); auto mote = dynamic_cast<const L2CapWiimote*>(&rhs);
if (!mote) if (!mote)
return false; return false;
return m_addr == mote->m_addr; return bacmp(&m_addr, &mote->m_addr) == 0;
} }