Retry opening of wiimote channels on initial failure #5997

There seems to be a race condition between a peripheral device
connecting to the bluetooth controller and it being ready to use.
It's very short and it depends upon the controller, some appear to
connect synchronously and block until the device is ready, others
report the device upon discovery but do not allow communication straight
away. I don't know which is the correct behaviour, or whether it depends
on the peripheral, controller or both. Anyway, Dolphin waits for a
remote to appear and immediately attempts to open the communication
channels, this can fail because the device isn't ready yet, delay, try
again, and it works.

There are other (unlikely) chances the device is busy at random
moments after this initial race condition so it loops around try to
reconnect.

This was inspired by an earlier patch, see here:
https://bugs.dolphin-emu.org/issues/5997#note-20

I can confirm that it works perfectly for me on a bluetooth
controller where otherwise it's impossible to connect (Dell 380
Bluetooth 4.0).
This commit is contained in:
Steven Newbury 2017-02-19 08:03:00 +00:00
parent 4c2b078017
commit e9a696b160

View file

@ -140,22 +140,52 @@ bool WiimoteLinux::ConnectInternal()
// Output channel
addr.l2_psm = htobs(WC_OUTPUT);
if ((m_cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
connect(m_cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
if (m_cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP))
{
int retry = 0;
while (connect(m_cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
{
// If opening channel fails sleep and try again
if (retry == 3)
{
WARN_LOG(WIIMOTE, "Unable to connect output channel to Wiimote: %s", strerror(errno));
close(m_cmd_sock);
m_cmd_sock = -1;
return false;
}
retry++;
sleep(1);
}
}
else
{
WARN_LOG(WIIMOTE, "Unable to open output socket to Wiimote: %s", strerror(errno));
close(m_cmd_sock);
m_cmd_sock = -1;
return false;
}
// Input channel
addr.l2_psm = htobs(WC_INPUT);
if ((m_int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
connect(m_int_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
if (m_int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP))
{
int retry = 0;
while (connect(m_int_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
{
// If opening channel fails sleep and try again
if (retry == 3)
{
WARN_LOG(WIIMOTE, "Unable to connect input channel to Wiimote: %s", strerror(errno));
close(m_int_sock);
close(m_cmd_sock);
m_int_sock = m_cmd_sock = -1;
return false;
}
retry++;
sleep(1);
}
}
else
{
WARN_LOG(WIIMOTE, "Unable to open input socket from Wiimote: %s", strerror(errno));
close(m_int_sock);
close(m_cmd_sock);
m_int_sock = m_cmd_sock = -1;
return false;